Я тестирую приложение, в котором создается метод и объект, и я пытаюсь проверить, действительно ли объект создается следующим образом:
@Test
public void testCreateWagerGetsCreated(){
DefaultSportsBettingService service = mock(DefaultSportsBettingService.class);
Player player = mock(Player.class);
Outcome outcome = new Outcome(null,"description",BigDecimal.valueOf(2),false);
BigDecimal bd = BigDecimal.valueOf(100);
assertNotNull(service.createWager(player,outcome, bd));
}
Однако тест не выдает эту ошибку:
org.opentest4j.AssertionFailedError: expected: not <null>
at org.junit.jupiter.api.AssertionUtils.fail(AssertionUtils.java:39)
at org.junit.jupiter.api.Assertions.fail(Assertions.java:134)
at org.junit.jupiter.api.AssertNotNull.failNull(AssertNotNull.java:47)
at org.junit.jupiter.api.AssertNotNull.assertNotNull(AssertNotNull.java:36)
at org.junit.jupiter.api.AssertNotNull.assertNotNull(AssertNotNull.java:31)
at org.junit.jupiter.api.Assertions.assertNotNull(Assertions.java:300)
at com.epam.training.sportsbetting.Tester.testCreateWagerGetsCreated(Tester.java:64)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Я пытался издеваться над классами домена и создавать их экземпляры, оба выдают одну и ту же ошибку. Что я делаю не так?
Класс игрока:
public class Player extends User{
private String name;
private BigDecimal balance;
private Currency currency;
public Player(){
}
public Player(String email, String password, String name, BigDecimal balance, Currency currency) {
super(email, password);
this.name = name;
this.balance = balance;
this.currency = currency;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public BigDecimal getBalance() {
return balance;
}
public void setBalance(BigDecimal balance) {
this.balance = balance;
}
public Currency getCurrency() {
return currency;
}
public void setCurrency(Currency currency) {
this.currency = currency;
}
@Override
public String toString() {
return "Player{" +
"name='" + name + '\'' +
", balance = " + balance +
", currency = " + currency +
'}';
}
}
Класс DefaultSportsBettingService:
public class DefaultSportsBettingService implements SportsBettingService{
public DummyDataStore dds = new DummyDataStore();
public List <Player> initializedPlayers = dds.getPlayerDatastore();
public List<User> initializedUsers = dds.getUserDataStore();
public List<Outcome> outcomeDatastore = dds.getOutcomeDatastore();
public List<SportEvent> sportEventDataStore = dds.getSportEventDataStore();
public List<Wager> wagerDatastore = dds.getWagerDatastore();
public List<Bet> betsDataStore = dds.getBetDataStore();
Player loggedPlayer;
@Override
public Player authenticateUser(User login) throws AuthenticationException {
Player find = new Player();
for (Player player : initializedPlayers) {
if (login.getEmail().equals(player.getEmail()) && login.getPassword().equals(player.getPassword())) {
loggedPlayer = player;
return loggedPlayer;
}
}
throw new AuthenticationException("Incorrect email and/or password");
}
@Override
public List<Bet> findAllBets() {
return dds.findAllBetVariations();
}
@Override
public Wager createWager(Player player, Outcome outcome, BigDecimal amount) throws LowBalanceException {
Wager wager = new Wager();
wager.setOutcome(outcome);
wager.setPlayer(player);
wager.setCurrency(player.getCurrency());
wager.setTimeStampCreated(LocalDateTime.now());
wager.setAmount(amount);
if (getLoggedPlayer().getBalance().compareTo(amount) < 0){
throw new LowBalanceException(loggedPlayer.getBalance().toString(), loggedPlayer.getCurrency());
}
getLoggedPlayer().setBalance(getLoggedPlayer().getBalance().subtract(amount));
if (wager.getOutcome().isWin()){
wager.setWin(true);
}
wagerDatastore.add(wager);
return wager;
}
@Override
public List<Wager> findAllWagers() {
return wagerDatastore;
}
@Override
public void calculateResults() {
BigDecimal counter = BigDecimal.valueOf(0);
for(int i = 0; i < wagerDatastore.size(); i++){
if (wagerDatastore.get(i).isWin()){
counter = counter.add(wagerDatastore.get(i).getOutcome().getOdd().multiply(wagerDatastore.get(i).getAmount()));
wagerDatastore.get(i).getPlayer().setBalance(counter);
}
}
}
public Player getLoggedPlayer() {
return loggedPlayer;
}
public void setLoggedPlayer(Player loggedPlayer) {
this.loggedPlayer = loggedPlayer;
}
}
Это упражнение я должен сделать, однако я еще не чувствую себя как дома в Мочикто.
Если вы хотите протестировать Сервис, вы не должны издеваться над ним. Макет будет возвращать null
каждый раз, если вы не указали when(service.createWager(any(), any(), any()).thenReturn(somethingNotNull);
, вы также можете использовать сопоставители, чтобы убедиться, что в метод передаются правильные значения. Но даже если вы добавите поведение, вы просто протестируете макет, ничего не выиграете от подобных тестов.
@Test public void testFindAllBetsIsNotNull(){ DefaultSportsBettingService service = mock(DefaultSportsBettingService.class); assertNotNull(service.findAllBets()); } В этом случае метод не дает сбоя, поэтому объект не является нулевым даже при фиктивном сервисе.
@ Mate25 Mate25 Добавьте, пожалуйста, полный класс и полный код тестирования. Не только метод тестирования. Еще раз, вы хотите проверить, что createWager
работает правильно, верно?
Да, я хочу проверить, правильно ли это работает, однако я с удовольствием выслушаю несколько советов, что я должен проверить и как, так как это мой первый раз, когда я тестирую, и мой единственный надежный источник информации, на который следует полагаться на основе Учебный материал, который я получил, представляет собой связанное видео, которое проверяет очень простую логику.
Несколько выпусков были объединены.
DefaultSportsBettingService
— это тестируемый объект, поэтому вы не хотите издеваться над ним.
В вашем случае NullPointerException
происходит от getLoggedPlayer
, поскольку loggerPlayer
никогда не инициализировалось.
Несколько менее важных вещей, которые делают тестирование ужасным:
LocalDateTime.now()
является статическим, поэтому вы не можете проверить, правильно ли он установлен, поэтому лучше передать его как внешний параметр (выходящий за рамки этих ответов)Примерное решение может выглядеть так (не могу протестировать его в IDE):
@ExtendWith(MockitoExtension.class)
class DefaultSportsBettingServiceTest {
@Mock
Player loggedPlayer
@InjectMocks
DefaultSportsBettingService service
@Test
public void testCreateWagerGetsCreated(){
Mockito.when(loggedPlayer.getBalance()).thenReturn(BigDecimal.ZERO);
Mockito.doNothing().when(loggedPlayer).setBalance(BigDecimal(15));
Player player = Player(); // May require more params
Outcome outcome = new Outcome(null,"description",BigDecimal.valueOf(2),false);
BigDecimal bd = BigDecimal.valueOf(100);
assertNotNull(service.createWager(player,outcome, bd));
}
}
По сути, вы имитируете loggedPlayer
, а остальные проходите как обычные объекты и ожидаете, что service.createWager
работает правильно. Отсюда Mockito должен предложить вам другие исправления, необходимые для тестирования кода или тестовых значений.
Спасибо за ваши усилия и время @Dmytro Chasovskyi. Вы рекомендуете вместо этого заглушить объект Player?
@ Mate25 Это зависит. Если вы спрашиваете, стоит ли вам stub
loggedPlayer — да, я рекомендую такой подход. Если вы спрашиваете о заглушке плеера, который идет с outcome
в качестве параметра - зачем вам это нужно?
Вам действительно нужно издеваться
Player player = mock(Player.class);
? Кроме того, зачем вам вообще здесь издеваться? Можете ли вы добавить реализацию классовPlayer
иDefaultSportsBettingService
? У вас установлены@RunWith
и@ExtendWith
mockito или другая библиотека для насмешек?