Samo
Samo

Reputation: 8240

How to re-initialize my bean

I have a bean in my applicationContext-test.xml that I use for mocking an external search engine. This way, when I run tests, any time my application code refers to this search engine, I know that I am using my mock engine instead of the real one.

A problem I am facing is that I want this engine to behave differently in different scenarios. For example, when I call getDocuments(), I usually want it to return documents. But sometimes I want it to throw an exception to make sure that my application code is handling the exception appropriately.

I can achieve this by referencing the bean in my test code and changing some stubs, but then I have to change the stubs back to what they were so that my other tests will also pass. This seems like bad practice for many reasons, so I'm seeking alternatives.

One alternative I considered was to reinitialize the bean completely. The bean is initialized from the applicationContext-test.xml with a static factory method. What I want to do is:

  1. Reference the bean from my test code to change some of its stubs
  2. Run the test using these new stubs
  3. At the end of this test, reinitialize the bean using the static factory method specified in applicationContext-test.xml

I tried something like this:

    ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(
            new String[] { "applicationContext-test.xml" });
    Factory factory = appContext.getBean(Factory.class);
    factory = EngineMocks.createMockEngineFactory();

But this does not do the trick. Any tests that are run after this will still fail. It seems that my new factory variable contains the Factory that I want and behaves accordingly, but when the bean is referenced elsewhere, getDocuments() still throws the exception that was stubbed in previously. Clearly, my re-initialization only affected the local variable and not the bean itself.

Can someone tell me how I can accomplish my goal?

Update

While I appreciate suggestions as to how to write better tests and better mocks, my goal is to reinitialize a bean. I believe there is value in learning how to do this whether it fits my use case or not (I believe it does fit my use case, but I'm having a hard time convincing some of my critics here).

The only answers that will get any up votes or green ticks from me are those which suggest how I can reinitialize my bean.

Upvotes: 0

Views: 1462

Answers (3)

Daniel Alexiuc
Daniel Alexiuc

Reputation: 13240

Instead of:

factory = EngineMocks.createMockEngineFactory();

do:

factory.callMethodThatChangesTheStateOfThisObjectSuchThatItIsSuitableForYourTest(withOptionalParameters);

Also, if you are using Spring Integration Testing, make sure to annotate your method with @DirtiesContext so it won't affect the next test.

Upvotes: 0

Belun
Belun

Reputation: 4169

How about injecting different implementations of the search engine? Just create more beans representing the different mocks of the search engine.

  • one test class is initialized with one mock and another test class with another mock; this, of course, means you'll have more test classes for a certain class that you are testing (not that good/clean)

or...

  • inject more mocks (of the search engine) in 1 testing class. some testing methods (from that testing class) use one mock, other testing methods use another mock

Upvotes: 0

Bozho
Bozho

Reputation: 597036

You should define the cases when you want a result and the cases when you want an exception. They should be differentiated by input parameters to the method. Otherwise it is not a good test. So, for a given set of parameters the output should be predictable.

Upvotes: 1

Related Questions