Java InjectMocks对象在单元测试中为空
这是我第一次使用Mockito进行junit测试。我面临@InjectMocks中使用的服务的NPE问题。我看了其他的解决方案,但即使遵循了它们,也显示了相同的结果。这是我的密码Java InjectMocks对象在单元测试中为空,java,junit,mockito,Java,Junit,Mockito,这是我第一次使用Mockito进行junit测试。我面临@InjectMocks中使用的服务的NPE问题。我看了其他的解决方案,但即使遵循了它们,也显示了相同的结果。这是我的密码 @RunWith(MockitoJUnitRunner.class) public class CustomerStatementServiceTests { @InjectMocks private BBServiceImpl bbService; @Before public
@RunWith(MockitoJUnitRunner.class)
public class CustomerStatementServiceTests {
@InjectMocks
private BBServiceImpl bbService;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
/**
* This test is to verify SUCCESS response
*/
@Test
public void testSuccess() {
BBResponse response = bbService.processDetails(txs);
assertEquals("SUCCESSFUL" ,response.getResult());
}
}
BBServiceImpl
Pom.xml
我的bbService对象在此为空
我有什么遗漏吗 我认为您误用了@InjectMocks注释
如果您有一个真正的类,通常是您想要测试的具有依赖项的类,它是有意义的,这些依赖项是通过构造函数注入或setter注入初始化的
另一方面,BBServiceImpl没有真正的依赖关系
现在,您可以手动为这些依赖项创建mock,然后创建受测类的实例,或者让mockito确定创建类的方法并为您注入mock。您仍然希望通过使用@Mock annotation来创建Mock,因为您确实希望在测试期间指定期望值
下面是一个示例,说明它应该是什么样子:
public interface BBService {
int process(String s); // simplified but still illustrates the concept
}
public class BBServiceImpl implements BBService {
//here is a dependency that should be mocked when we will test BBServiceImpl class
private SizeCalculator sizeCalculator;
// I use constructor injection here
public BBServiceImpl(SizeCalculator sizeCalculator) {
this.sizeCalculator = sizeCalculator;
}
public int process(String s) {
// here is a dependency invocation
return sizeCalculator.calculateSize(s);
}
}
正如您所看到的,该实现有一个真正的依赖关系,可以在测试期间进行模拟
现在,此依赖项看起来像:
public interface SizeCalculator {
int calculateSize(String s);
}
public class SizeCalculatorImpl implements SizeCalculator {
public int calculateSize(String s) {
return s.length();
}
}
好的,现在让我们为BBServiceImpl创建一个测试。我们不希望创建SizeCalculator Impl,而是希望为其提供一个模拟,并在运行时生成的代理上指定一个期望值,该代理由接口SizeCalculator创建:
注意这一行
@InjectMocks
private BBServiceImpl underTest;
Mockito将找到构造函数并注入mock
当然,在这种情况下,我们可以手动执行:
@RunWith(MockitoJunitRunner.class)
public class SampleManualTest {
@Mock
private SizeCalculator sizeCalc;
private BBServiceImpl underTest;
@Before
public void init() {
this.underTest = new BBServiceImpl(sizeCalc);
}
}
但是想想在类BBServiceImpl中有许多依赖项的情况,InjectMocks在这种情况下会更方便。如果使用setter注入,这种方式可以节省对setter的显式调用。我认为您误用了@InjectMocks注释
如果您有一个真正的类,通常是您想要测试的具有依赖项的类,它是有意义的,这些依赖项是通过构造函数注入或setter注入初始化的
另一方面,BBServiceImpl没有真正的依赖关系
现在,您可以手动为这些依赖项创建mock,然后创建受测类的实例,或者让mockito确定创建类的方法并为您注入mock。您仍然希望通过使用@Mock annotation来创建Mock,因为您确实希望在测试期间指定期望值
下面是一个示例,说明它应该是什么样子:
public interface BBService {
int process(String s); // simplified but still illustrates the concept
}
public class BBServiceImpl implements BBService {
//here is a dependency that should be mocked when we will test BBServiceImpl class
private SizeCalculator sizeCalculator;
// I use constructor injection here
public BBServiceImpl(SizeCalculator sizeCalculator) {
this.sizeCalculator = sizeCalculator;
}
public int process(String s) {
// here is a dependency invocation
return sizeCalculator.calculateSize(s);
}
}
正如您所看到的,该实现有一个真正的依赖关系,可以在测试期间进行模拟
现在,此依赖项看起来像:
public interface SizeCalculator {
int calculateSize(String s);
}
public class SizeCalculatorImpl implements SizeCalculator {
public int calculateSize(String s) {
return s.length();
}
}
好的,现在让我们为BBServiceImpl创建一个测试。我们不希望创建SizeCalculator Impl,而是希望为其提供一个模拟,并在运行时生成的代理上指定一个期望值,该代理由接口SizeCalculator创建:
注意这一行
@InjectMocks
private BBServiceImpl underTest;
Mockito将找到构造函数并注入mock
当然,在这种情况下,我们可以手动执行:
@RunWith(MockitoJunitRunner.class)
public class SampleManualTest {
@Mock
private SizeCalculator sizeCalc;
private BBServiceImpl underTest;
@Before
public void init() {
this.underTest = new BBServiceImpl(sizeCalc);
}
}
但是想想在类BBServiceImpl中有许多依赖项的情况,InjectMock在这种情况下会更方便+如果使用setter注入,这种方式可以保存对setter的显式调用。在提供了附加信息的讨论之后,答案可以总结为junit4和junit5之间的maven配置问题 stacktrace清楚地显示了junit5引擎的用法 pom还包括以下依赖项:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.2.5.RELEASE</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
在SpringBoot2.2.0.0发布之前,SpringBootStarter测试过渡地包含junit4依赖项。从SpringBoot2.2.0开始,JUnitJupiter被包括在内
根据这一点,排除似乎阻止了执行
消除隔离为我解决了这个问题
如果没有使用junit4的明显要求,我建议切换到junit5
有关如何将mockito与junit5一起使用的更多信息,请查看此链接 在提供了额外信息的讨论之后,答案可以总结为junit4和junit5之间的maven配置问题 stacktrace清楚地显示了junit5引擎的用法 pom还包括以下依赖项:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.2.5.RELEASE</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
在SpringBoot2.2.0.0发布之前,SpringBootStarter测试过渡地包含junit4依赖项。从SpringBoot2.2.0开始,JUnitJupiter被包括在内
根据这一点,排除似乎阻止了执行
消除隔离为我解决了这个问题
如果没有使用junit4的明显要求,我建议切换到junit5
有关如何将mockito与junit5一起使用的更多信息,请查看此链接 测试类是否用@ExtendsWithMockitoJUnitRunner.class注释?你申报了吗?Mock是否用@Mock=注释?请发布一个@Turing85,是的,它用@RunWithMockitoJUnitRunner.classis注释。如果您使用@RunWithMockitoJUnitRunner.class,则不需要MockitoAnnotations.initMocksthis;A.
lso,共享BBServiceImpl的代码。请检查BBServiceImpl类中是否有任何类级属性或是否使用了任何非参数构造函数。测试类是否用@ExtendsWithMockitoJUnitRunner.class注释?你申报了吗?Mock是否用@Mock=注释?请发布一个@Turing85,是的,它用@RunWithMockitoJUnitRunner.classis注释。如果您使用@RunWithMockitoJUnitRunner.class,则不需要MockitoAnnotations.initMocksthis;另外,共享BBServiceImpl的代码。请检查BBServiceImpl类中是否有任何类级属性或是否使用了任何非参数构造函数。导致问题的是mockito core的版本。引起问题的是mockito core的版本。