如何解决无法使用@Rule和@RunWith批注,但已弃用的initmocks可以工作
我正在研究一个简单的Java程序的基本测试驱动开发学习,该程序可以为股票提供投资组合价值。
我有2个课程,Portfolio.java
和Stock.java
描述了投资组合和股票模型。 StockService.java
接口以抽象方式用于获取实时股价。
PortfolioTest.java
是我试图通过使用Mockito模拟此StockService来为投资组合功能编写单元测试的类。
我能够使用已弃用的MockitoAnnotations.initMocks(this);
并运行测试,但是如果尝试使用@Rule
或@RunWith
批注,则会出现空指针异常。
Stock.java
public class Stock {
private String name;
private int quantity;
public Stock(String name,int quantity) {
this.name = name;
this.quantity = quantity;
}
public String getName() { return name; }
public float getQuantity() { return quantity; }
}
Portfolio.java
import java.util.List;
public class Portfolio {
private List<Stock> stocks;
private StockService stockService;
private Float portfoliovalue;
public Portfolio(List<Stock> stocks,Float portfoliovalue) {
this.stocks = stocks;
this.portfoliovalue = portfoliovalue;
}
public void setStockService(StockService stockService) { this.stockService = stockService; }
public Float calculateMarketValue() {
Float marketValue = 0.0f;
for(Stock stock: this.stocks) {
marketValue += (stock.getQuantity()*stockService.getRealtimePrice(stock.getName()));
}
return marketValue;
}
public Boolean isInProfit() {
return (portfoliovalue<calculateMarketValue()?true:false);
}
}
StockService.java
public interface StockService {
public float getRealtimePrice(String name);
}
pom.xml
<project>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.5.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-runner</artifactId>
<version>1.5.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.5.13</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<finalName>mockito-basic</finalName>
</configuration>
</plugin>
</plugins>
</build>
</project>
PortfolioTest.java
//@RunWith(MockitoJUnitRunner.class)
public class PortfolioTestMockAnnotations {
//@Rule public MockitoRule rule = MockitoJUnit.rule();
@Mock
StockService stockService;
@InjectMocks
Portfolio portfolio;
@BeforeAll
static void setUp() {
}
@BeforeEach
void init(){
MockitoAnnotations.initMocks(this);
System.out.println(stockService);
when(stockService.getRealtimePrice("infosys")).thenReturn(2200.0f);
when(stockService.getRealtimePrice("reliance")).thenReturn(3100.0f);
when(stockService.getRealtimePrice("indiamart")).thenReturn(4000.0f);
List<Stock> stocks = new ArrayList<>();
stocks.add(new Stock("infosys",10));
stocks.add(new Stock("reliance",5));
portfolio = new Portfolio(stocks,35000.0f);
portfolio.setStockService(stockService);
}
@Test
public void calculateMarketValuetest() {
Assertions.assertEquals(portfolio.calculateMarketValue(),37500);
}
@Test
public void calculateIsInProfittest() {
Assertions.assertTrue(portfolio.isInProfit());
}
}
在PortfolioTest.java中使用initmocks()可以平稳地运行测试。
请提出正确使用@Rule和@RunWith的正确方法。还提供了这三种实例化模拟机制之间的简要区别。
解决方法
您的POM显示您可能会以某种方式混合使用JUnit5和JUnit4。有两个注释可以将方法声明为测试:
@org.junit.Test // for JUnit4
@org.junit.jupiter.api.Test // for JUnit5
如果您为 JUnit4 进行注释并以JUnit4测试的身份运行测试,那么一切都会很好。
但是,如果您使用JUnit5进行注释并作为JUnit5运行,则情况将有所不同。 JUnit5既不使用@Rule
也不使用@RunWith
,但是有其自己的方法来初始化模拟。 Article可以解释为什么有些东西起作用而有些东西不起作用。
简而言之,要以JUnit5身份运行,您的类应具有注释:
@ExtendWith(MockitoExtension.class)
因为@Rule
或RunWith
不再起作用。此注释需要依赖项:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>2.23.0</version>
<scope>test</scope>
</dependency>
我只运行JUnit5并具有这些依赖项
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.5.2</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>2.23.0</version>
<scope>test</scope>
</dependency>
,
在 Junit5 中,@RunsWith() 被替换为 @ExtendWith({MockitoExtension.class}),其中 MockitoExntension 来自于
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-junit-jupiter -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>3.11.2</version>
<scope>test</scope>
</dependency>
3.11.2 是我发布解决方案时的当前版本。有关更多信息,您可以访问:Mockito and Junit5
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。