0

I have a problem with one test.

Let's say, there was a method like this:

public Item doSomething(Some parameters) {
    Item item = someMethodDoingSomethingWithParameters(parameters)
    return item;
}

but then I have introduced new functionality, sending notifications.

public Item doSomething(List<Some> parameters) {
    Item item = someMethodDoingSomethingWithParameters(parameters)
    sendNotificationToItemOwners(parameters);
    return item;
}

this sendNotificationToItemOwners(List<Some> parameters) method looks like this:

private void sendNotificationToOwners(parameters) {
    parameters.stream().forEach(parameter -> notificationService.sendNotification(paremeter.getOwnerEmail());
}

I don't want to test a lambda, and I don't want to test the NotificationService cause it is allready well tested.

The code I wrote is a very simplified version of my original code. The addition of this new sendNotificationToOwners() method gives me headaches, the test is failing, I am trying to mock some objects required, but it doesn't seem to solve my problem.

Can I completely omit this method in a test? It would be wonderful if it would be possible..

dziki
  • 1,360
  • 1
  • 15
  • 38
  • 1
    no u cannot. but it is not hard to mock notificationService. Put your Class under Test and Your Test class. – pvpkiran Mar 27 '20 at 18:53
  • 2
    Indeed, you can't omit it (at least not without finding a framework that would do bytecode modification, which would not be a route you'd want to take), but mocking the service is idiomatic and should be easy. – Kayaman Mar 27 '20 at 18:56
  • This new method is part of the *desired behavior* of your unit under test. Therefore it should be tested tough. But as the others pointed out you should mock the `notificationService` and verify that its method `sendNotification()` is called with each entry of the `parameters` collection. – Timothy Truckle Mar 27 '20 at 21:03
  • No. In Unit Test you test your public API and assert for behavior you expect. Since it invokes a private method you do want to test that interaction by mocking `notificationService`. If the `lamda` code is huge, follow Single Responsibility Principle, and refactor it to it's own `class`. – VinPro Mar 28 '20 at 21:50

1 Answers1

0

I don't want to test a lambda,

Lambda expressions aren't exempt from unit testing. I'd say it's a pretty dangerous way of looking at them.

and I don't want to test the NotificationService cause it is already well tested.

Mock it then and allow an instance to be injected into the class under test via a constructor or a factory method (or annotate the field if you're using a dependency injection framework). Your private lambda will still execute but won't actually use the other, possibly complex class. If the class being tested here doesn't already allow an instance of NotificationService to be provided upon creation, refactor it so that inversion of control can be achieved.

Can I completely omit this method in a test? It would be wonderful if it would be possible..

Technically, instead of injecting a NotificationService reference, you could extract the private method sendNotificationToOwners to a separate class and inject/mock that. However, that class would just iterate over the parameters and invoke NotificationService. Seems like a bit of an overkill. My preference would be to inject NotificationService and just let the lambda run and invoke sendNotification on a mock/spy object. That would also allow you to test that NotificationService has been called for each parameter.

toniedzwiedz
  • 16,077
  • 8
  • 79
  • 118