I need some advice on how to use Moq in a unit test to make sure that my class under test is behaving how I want. That is the class under test publishes an Event Aggregator (from Prism) event and I need some way of asserting that this event has been raised in my test.
I don't have a lot of resource at work and am finding it difficult to know how to set this up.
I have :-
public SomeEvent : CompositePresentationEvent<SomeEvent>
{
EventPayload
}
public SomeClass
{
void Allocate(){EventAggregator.Publish<SomeEvent>}
}
public SomeService : IService
{
SomeService(){ EventAggregator.Subscribe<SomeEvent>(DoSomething)}
void DoSomething(SomeEvent evt){}
}
I think that if my test is for SomeClass I need to verify that if I call SomeClass.Allocate a SomeEvent message is being published. How is this done?
Do I also need to verify that a mocked SomeService is receiving the SomeEvent? Or is that a seperate unit test that belongs to SomeService unit test and not SomeClass?
In any event, not sure how to set any of this up so any advice would be appreciated.
You would supply SomeClass with an IEventAggregator, which will allow you to supply a mock during testing:
public SomeClass(IEventAggregator eventAggregator)
{
_eventAggregator = eventAggregator;
}
Then your test would look something like this:
var fakeEventAggregator = new Mock<IEventAggregator>();
var fakeEvent = new Mock<SomeEvent>();
fakeEventAggregator.
Setup(x => x.GetEvent<SomeEvent>()).
Returns(fakeEvent.Object);
var test = new SomeClass(fakeEventAggregator.Object);
test.Allocate();
fakeEvent.Verify(x => x.Publish(It.IsAny<SomeEventArgs>()));
If these are unit tests then you would test the subscription entirely separately in the SomeService tests. You are testing that SomeClass correctly publishes an event and that SomeService behaves correctly when it is given an event to process.
Related
I am trying to write an integration test for JMS service which looks like something like this.
#JmsListener(destination = "mailbox", containerFactory = "myFactory")
public void receiveMessage(Email message) throws InterruptedException {
try {
sendEmail(message);
}catch (Exception e){
LOGGER.log(Level.SEVERE,"Failed to deliver email",e);
Thread.sleep(TimeUnit.SECONDS.toSeconds(Optional.of(retryInterval).orElse(5)));
throw e;
}
}
private void sendEmail(Email message){
...............
}
First of all, can I mock this some how? I tried mocking it, but when I send a message the spring boot application is calling the actual JMS bean not the mock one. Seems like this is not possible.
Even if this is not possible, can I at least aoutowire the bean and somehow check if the receiveMessage method is being invoked. Furthermore, if it is being invoked, the sendEmail part should be faked so that it does not do any work. I have a few ideas such as creating a subclass for testing, but not happy with either of them. So wanted to if you can suggest me a better work around?
One approach is to use different profiles for say development, integration test and production and annotate the different components and your integration test class accordingly.
#Component
#Profile("it")
public class MessageReceiverIT {
#JmsListener(destination = "mailbox", containerFactory = "myFactory")
public void receiveMessage(SimpleMessage email) {
log.info("Integration test pretend to receive {}", email);
// (...)
This is the Integration test that uses the same Application class as the real Application, but if a message is received the MessageReceiverIT.receiveMessage() method will be invoked instead of the production component:
#RunWith(SpringRunner.class)
#SpringBootTest(classes=Application.class)
#ActiveProfiles("it")
public class JmsIntegrationTest {
#Inject
ConfigurableApplicationContext context;
#Test
public void testSend() throws Exception{
JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
jmsTemplate.convertAndSend("mailbox", new SimpleMessage("it", "we need more IT"));
// (...)
Also check out Spring Boot Testing for alternative approaches such as the use of #TestConfiguration. I'm using Spring Boot in my examples, but there should be similar approaches if you have a none Spring Boot Application.
I have an Actor and when it recieves a StartMessage, it should change state using Become(Started). How do I unit test whether or not the Actor's state has changed to Started() ?
MyActor class
public class MyActor : ReceiveActor
{
public MyActor()
{
Receive<StartMessage>(s => {
Become(Started); // This is what I want to unit test
});
}
private void Started()
{
Console.WriteLine("Woo hoo! I'm started!");
}
}
Unit Test
[TestMethod]
public void My_actor_changes_state_to_started()
{
// Arrange
var actor = ActorOfAsTestActorRef<MyActor>(Props.Create(() => new MyActor()));
// Act
actor.Tell(new StartMessage());
// Assert
var actorsCurrentState = actor.UnderlyingActor.STATE; // <-- This doesn't work
Assert.AreEqual(Started, actorsCurrentState);
}
UPDATE
Related to the answer from tomliversidge: My reason for writing this unit test was academic but in reality, it's not a good unit test which is why you aren't able to do it as I'd hoped. From Petabridge's Unit Testing Guide:
In reality, if one actor wants to know the internal state of another actor then it must send that actor a message. I recommend you follow the same pattern in your tests and don’t abuse the TestActorRef. Stick to the messaging model in your tests that you actually use in your application.
You would normal test this by message passing. For example, what messages do you process in the Started state? I'm presuming your example has been simplified to the Console.WriteLine action inside of Started.
If you send the StartMessage and then a second message that is processed when in the Started state you can then assert on a response to this second message.
As a simple suggestion:
private void Started()
{
Receive<StartMessage>(msg => {
Sender.Tell(new AlreadyStarted());
}
}
if StartMessage is received whilst in the Started state, you can then assert on receiving an AlreadyStarted message.
For more info check out the Petabridge article https://petabridge.com/blog/how-to-unit-test-akkadotnet-actors-akka-testkit/
What is the best practice to test a Grails Service which depends on another Service?
The default mixin TestFor correctly inject the service under test, for eg:
#TestFor(TopService)
class TopServiceTests {
#Test
void testMethod() {
service.method()
}
}
but if my instance of TopService (service) relies on another Service, like InnerService:
class TopService {
def innerService
}
innerService will not be available, dependency injection doesn't seem to fill this variable. How should I proceed?
Integration tests should not use the #TestFor annotation, they should extend GroovyTestCase. The test annotations are only for unit tests (and will have bad behavior when used in integration tests, especially the #Mock annotations). You're seeing one of those bad behaviors now.
If you extend GroovyTestCase you can then just have
def topService
At the top of your test and it'll get injected with all of it's dependencies injected.
For a unit test case, you'd just want to add new instances of associated services to your service in a setUp method. Just like:
#TestFor(TopService)
class TopServiceTests {
#Before public void setUp() {
service.otherService = new OtherService()
}
...
I have a CustomerRegistrationServiceTest and my CustomerRegistrationService depends on the PasswordService.
my CustomerRegistrationService just autowires it like normal:
class CustomerRegistrationService {
def passwordService
In my CustomerRegistrationServiceTest I have:
#TestFor(CustomerRegistrationService)
#Mock(Customer)
class CustomerRegistrationServiceTests extends GrailsUnitTestMixin {
void setUp() {
mockService(PasswordService)
}
So when I test the CustomerRegistrationService, it is able to access the PasswordService
I have an AuthenticationManager.authenticate(username,password) method that gets called in someMethod of a SomeService under test. The AuthenticationManager is injected into SomeService:
#Component
public class SomeService {
#Inject
private AuthenticationManager authenticationManager;
public void someMethod() {
authenticationManager.authenticate(username, password);
// do more stuff that I want to test
}
}
Now for the unit test I need the authenticate method to just pretend it worked correctly, in my case do nothing, so I can test if the method itself does the expected work (Authentication is tested elsewhere according to the unit testing principles, however authenticate needs to be called inside that method) So I am thinking, I need SomeService to use a mocked AuthenticationManager that will just return and do nothing else when authenticate() gets called by someMethod().
How do I do that with PowerMock (or EasyMock / Mockito, which are part of PowerMock)?
With Mockito you could just do that with this piece of code (using JUnit) :
#RunWith(MockitoJUnitRunner.class)
class SomeServiceTest {
#Mock AuthenitcationManager authenticationManager;
#InjectMocks SomeService testedService;
#Test public void the_expected_behavior() {
// given
// nothing, mock is already injected and won't do anything anyway
// or maybe set the username
// when
testService.someMethod
// then
verify(authenticationManager).authenticate(eq("user"), anyString())
}
}
And voila. If you want to have specific behavior, just use the stubbing syntax; see the documentation there.
Also please note that I used BDD keywords, which is a neat way to work / design your test and code while practicing Test Driven Development.
Hope that helps.
I am writing client-side components in a provided framework, and need to be able to unit test my components. The components are written using MVP (Model-View-Presenter) pattern, I want to use PEX to automatically generate unit tests for my presenters.
The following is the code of a presenter.
public partial class CompetitorPresenter : PresenterBase
{
private readonly ICompetitorView _view;
public IGlobalDataAccess GlobalDataAccess;
public IGlobalUI Globals;
public SystemClient Client;
public bool DeleteRecord()
{
if (_view.CompetitorName != "Daniel")
return false;
if (Client.SystemName != "Ruby")
return false;
return true;
}
}
The problem I am having is that the object SystemClient is provided by the framework, and I cannot use a factory class to create an instance of SystemClient. Therefore when I run PEX to automatically generate unit tests, I have to tell PEX to ignore SystemClient, the result of this is that the method DeleteRecord is not fully covered as the line Client.SystemName != "Ruby" is not tested.
Since I have the mock object MSystemClient (created using moles), I am wondering if somewhere in the configuration I could tell PEX to use MSystemClient, and let PEX to automatically generate test cases to fully cover this method.
You are on the right track. If you cannot control where the instance of CompetitorPresenter.Client is created, you can define a mole for all instances:
MSystemClient.AllInstances.SystemNameGet = () => "SomeName";
Your unit test has to be run in a "hosted environment":
[HostType("Moles")]
public void TestMethod()
{
MSystemClient.AllInstances.SystemNameGet = () => "SomeName";
// Test code...
}