呼叫模拟方法时,Spring Mockito测试失败



这是两个弹簧Service;

public interface Service01 {
     String test01(String name);
}
@Service 
public class Service01Impl implements Service01 { 
     @Override
     public String test01(String name) {
          if (!"123".equals(name)) {
              throw new RuntimeException("name is illegal");
          }
          return name;
     }
}
@Service 
public class Service02 { 
     @Autowired
     private Service01 service01;
     @Autowired
     private Service03 service03;
     public String test02(String name) {
          service03.checkNameNotNull(name);
          return service01.test01(name);
     }
}
@Service 
public class Service03 { 
     public void checkNameNotNull(String name) {
          if (name == null) {
              throw new RuntimeException("name is null");
          }
     }
}

那是我的测试频道:

public class TestCalss {
    @Mock
    private Service01 service01;
    @Autowired
    private Service02 service02;
    @Test
    public void testMock() {
        // mock service
        when(service01.name("abc")).thenReturn("mock return abc");
        // here will be success
        String nameAbc = service01.test01("abc")
        Assert.assertEquals("mock return abc", nameAbc);
        // but here got exception: `name is illegal`
        String name = service02.test02("abc");
        Assert.assertEquals("mock return abc", name);
    }
}

Q1:为什么在ROW中得到例外:String name = service02.test02("abc");

java.lang.RuntimeException: name is illegal

Q2:打电话给Service02时如何模拟Service01

- 编辑

Q2用@InjectMocks

固定

Q3:如何仅模拟Service01,但是Service03没有模拟

我想做这张支票没有模拟 service03.checkNameNotNull(name);

设置模拟时需要使用参数摩擦器 - 而不是传递字符串字面的"abc",您需要行看起来像when(service01.name(eq("abc"))).thenReturn...

如果您不介意传递的实际字符串是什么,那么还有其他匹配器也可以使用anyString()

您也不想在测试中使用@Autowired - 如果您希望正在测试的班级自动注入模拟,则需要实例化模拟并注入模拟而不是真正的弹簧豆。p>最直接的方法是使用MockitoJUnitRunner@InjectMocks注释:

@RunWith(MockitoJUnitRunner.class)
public class TestCalss {
    @Mock
    private Service01 service01;
    @InjectMocks
    private Service02 service02;
...

要注入一个不是模拟的类,您需要使用@Before注释,并以某种方式将对象传递到类中(就像您在普通Java代码中一样)。

我首选的方法是拥有一个构造函数,将依赖项设置为班级的私人最终字段,但是Spring还提供了一个类ReflectionTestUtils,如果您真的想坚持使用没有设定器的私有字段,则可以使用。

这样的东西:

@Service 
public class Service02 { 
     private final Service01 service01;
     private final Service03 service03;
     @Autowired
     public Service02 (Service01 service01, Service03 service03) {
         this.service01 = service01;
         this.service03 = service03;
     }
    ...
}
@RunWith(MockitoJUnitRunner.class)
public class TestClass {
    @Mock
    private Service01 service01;
    private Service02 underTest;
    @Before
    public void setup() {
        this.underTest = new Service02(this.service01, new Service03());
    }
    ...
}

如果您想在原本要模拟的对象上调用真实方法,那么这可能是您的班级做太多的迹象,实际上应该是两个或多个较小的班级,但这也可能是可能的:when(someMock.someMethod()).thenCallRealMethod();

相关内容

  • 没有找到相关文章

最新更新