I use Spock framework to run my tests. Each test class has Spring's annotation #ContextConfiguration over it. As I see context is brought up for every test class and it takes a lot of time to run a couple of dozens of tests in different classes. Is there a way to configure Spock test classes to run under common spring context?
It's not about spock but about spring.
Spring can cache in general application context across many test cases but you have to know how to do it right.
As a first resort, make sure, that 'locations' attribute of #ContextConfiguration is the same.
In addition, it's possible to take advantage of #ContextHierarchy annotation.
This caching facility is quite fragile, but works.
Maybe it makes sense to create a common specification with all the annotation and inherit from it:
#ContextConfiguration(locations = ...)
// or maybe
#ContextHierarchy (...)
public abstract class MyCommonSpec extends Specification {
}
// and not in tests:
public class MyTest1 extends MyCommonSpec {
...
}
public class MyTest2 extends MyCommonSpec {
...
}
Here is a link on a very relevant discussion
Possible approach that will work: create multiple classes with tests. For example, A, B, C, D. Make inheritance like: D -> C -> B -> A. Run tests in D, this will execute all the tests from A,B,C,D under common spring context.
I assume that this approach is not so neat and perfect, but it solves initial problem.
Related
JUnit4 has #FixMethodOrder annotation which allows to use alphabetical order of test methods execution. Is there analogous JUnit5 mechanism?
Edit: JUnit 5.4 is officially released now, so no need to use snapshots anymore.
This is now possible with JUnit 5.4.
https://junit.org/junit5/docs/current/user-guide/#writing-tests-test-execution-order
To control the order in which test methods are executed, annotate your
test class or test interface with #TestMethodOrder and specify the
desired MethodOrderer implementation. You can implement your own
custom MethodOrderer or use one of the following built-in
MethodOrderer implementations.
Alphanumeric: sorts test methods alphanumerically based on their names
and formal parameter lists.
OrderAnnotation: sorts test methods numerically based on values
specified via the #Order annotation.
No, not yet. For unit tests, execution order should be irrelevant. For more complex tests, JUnit is aiming to provide explicit support - test ordering would be part of that.
With version 5.8.0 onwards, test classes can be ordered too.
src/test/resources/junit-platform.properties:
# ClassOrderer$OrderAnnotation sorts classes based on their #Order annotation
junit.jupiter.testclass.order.default=org.junit.jupiter.api.ClassOrderer$OrderAnnotation
Other Junit built-in class orderer implementations:
org.junit.jupiter.api.ClassOrderer$ClassName
org.junit.jupiter.api.ClassOrderer$DisplayName
org.junit.jupiter.api.ClassOrderer$Random
For other ways (beside junit-platform.properties file) to set configuration parameters refer here.
You can also provide your own orderer. It must implement ClassOrderer interface:
package foo;
public class MyOrderer implements ClassOrderer {
#Override
public void orderClasses(ClassOrdererContext context) {
Collections.shuffle(context.getClassDescriptors());
}
}
junit.jupiter.testclass.order.default=foo.MyOrderer
Note that #Nested test classes cannot be ordered by a ClassOrderer.
Refer to JUnit 5 documentations and ClassOrderer api docs to learn more about ordering test classes.
I am not sure if what i am doing is actually the "correct" way of doing unit tests with DI. Right now i ask my ViewModelLocator to actually create all the instances i need, and just get the instance i need to test, which makes it very simple to test a single instance because lets asume that Receipt needs a Reseller object to be created, reseller needs a User object to be created, user need some other object to be created, which creates a chain of objects to create just to test one single instance.
With di usally interfaces will get mocked and parsed to the object which you would like to create, but how about simple Entities/ViewModels?
Whats the best practice to do unit testing with DI involved?
public class JournalTest
{
private ReceiptViewModel receipt;
private ViewModelLocator locator;
[SetUp]
public void SetUp()
{
locator = new ViewModelLocator();
receipt = SimpleIoc.Default.GetInstance<ReceiptViewModel>();
}
[TearDown]
[Test]
public void CheckAndCreateNewJournal_Should_Always_Create_New_Journal()
{
receipt.Sale.Journal = null;
receipt.Sale.CheckAndCreateNewJournal();
Assert.NotNull(receipt.Sale.Journal);
}
}
First, you aren't using Dependency Injection in your code. What you have there is called Service Locator (Service Locators create a tight coupling to the IoC/Service Locator and makes it hard to test).
And yes, it's bad (both Service Locator and Dependency Injection), because it means: You are not doing a UnitTest, you are doing an integration Test.
In your case the ReceiptViewModel will not be tested alone, but your test also tests the dependencies of ReceiptViewModel (i.e. Repository, Services injected etc.). This is called an integration test.
A UnitTest has to test only the class in question and no dependencies. You can achieve this either by stubs (dummy implementation of your dependencies, assuming you have used interfaces as dependencies) or using mocks (with a Mock framework like Moq).
Which is easier/better as you don't have to implement the whole class, but just have to setup mocks for the methods you know that will be required for your test case.
As an additional note, entities you'll got to create yourself. Depending on your UnitTest framework, there may be data driven tests (via Attributes on the test method) or you just create them in code, or if you have models/entities used in many classes, create a helper method for it.
View Models shouldn't be injected into constructor (at least avoided), as it couples them tightly
Units tests should run quickly and should be deterministic. That means you have to mock/stub everything that brokes these two rules.
The best way to mock/stub dependancies is to inject them. In the production, classes are assembled by DI framework, but in unit tests you should assemble them manually and inject mocks where needed.
There is also a classic unit test approach where you stub/mock every dependency of your class, but it's useless since you don't gain anything by that.
Martin Fowler wrote great article about that: link
You should also read Growing Object-oriented software: Guided by tests. Ton of useful knowledge.
I need to MOQ wcfClientService while calling the SomeMethod().
Class ABC : IABC
{
internal WcfClientService wcfClientService = new WcfClientService();
public void SomeMethod(object pqr)
{
using(wcfClientService)
{
wcfClientService.Save(some parameters)
}
}
}
With the current implementation, you cannot isolate the "ABC" class as it is tightly coupled with wcfClientService. I would strongly suggest things mentioned below:
Extract an interface IClientService. This makes your "ABC" class depend on an abstraction instead of a concrete implementation. It will help in short term to isolate "ABC" better for unit testing. In long term, your "ABC" class would not have to be changed if a "RestfulClientService" was to be used.
Consider introducing a Dependency Injection framework. Anything like a Spring.Net, Unity or Autofac should serve the purpose. Ideally, your production code should never instantiate a dependency. Let the framework take care of it.
Now, register and resolve a mock implementation of the interface using the DI framework and start unit testing the "ABC" class.
I have a very simple package structure, only one level deep for all my grails artifacts- the name of the application "estra"- because the grails application structure is already providing the separation folders. But when writing unit-tests all the classes are inside the same estra.* package and I want to keep them separated like this estra.domain, estra.controllers, etc.
Right now everything works fine, but the tests are pretty simple. Will I face any problem in the future with dependency injection or something?
No, the package name don't influence in your test since in your test class you "say" which class is tested, using the #TestFor annotation. But remember that in unit tests you need to manually set your dependencies.
class ServiceOne {
def serviceTwo
}
#TestFor(ServiceOne)
class ServiceOneTests {
#Before
public void setup() {
service.serviceTwo = new ServiceTwo() //or mocked instance...
}
}
I have two Controller unit tests and each one sets an HttpClient metaclass execute in setUp() like the following:
HttpClient.metaClass.execute = { HttpUriRequest request ->
<return expected data for my tests>
}
Then I attempt to tear down the metaClass in tearDown() with the following code:
protected void tearDown() {
super.tearDown()
GroovySystem.metaClassRegistry.removeMetaClass(HttpClient.class)
}
However only one of my unit tests passes because the return from the HttpClient is incorrect/unexpected. If I add the logic needed for both tests in the metaClass.execute of both tests I get no testing failures. However this is cumbersome and impractical, especially in an agile development environment.
What am I doing wrong with trying to tear down this HttpClient metaclass registration? How can I troubleshoot this further?
I'm currently using grails 1.3.7 on a CentOS 5 install.
Edit: I should clarify that my problem is that the metaClass override is causing issues between test classes, not test cases. We've been setting up the metaClass override so that it will return correct data for all of the test cases in a given class. So Test class A has the metaClass data for it's test cases and Test class B has the metaClass data for it's test cases. The issue is that since Test class A gets tested first, test class B ends up using the metaClass definition from test class A and fails because of this.
You shouldn't need to implement a tearDown method. Assuming you're extending ControllerUnitTestCase or GrailsUnitTestCase If you call registerMetaClass HttpClient before you metaClass the execute method it will replace the metaClass for HttpClient in between test classes for you. I've never used the removeMetaClass method so I don't know why that wouldn't be working so I can't answer the question of why that doesn't work, but this should get you past your issue.
...
registerMetaClass HttpClient
HttpClient.metaClass.execute = { HttpUriRequest request ->
<return expected data for my tests>
}
The solution I ended up using is a bit of a hack but it's easier to maintain. I just made a class in src/groovy that creates the HttpClient.metaClass and then just made each test class that needs it run the static method on the new class. That way all of the necessary code for the meta classing is in one place.