I´m trying to write some unit tests for my company, so its not possible for me to change anything in sourceCode but everything in the tests.
I´m using Java8, Spring, Mockito and JUnit4.
Problem: There are some services with a entityManager, which gets instantiated via dependencyInjection
#PersistenceContext(unitName = someName)
private EntityManager em;
I tried to mock this and injecting it into my ClassUnderTest, like i mocked every other class but that doesn´t work.
#InjectMocks
#Autowired
private SomeService testedSomeService;
There´s always an "IllegalStateException: Failed to load application context" before running the first test, with a hint to the entity manager.
If i make the annotation to a comment, every method gets tested fine (except the methods, using entityManager).
Is there a simple way to mock the entityManager? or how can i inject a dependency in my testclass?
I appreciate ANY help!
Try this:
#RunWith(MockitoJUnitRunner.class)
public class Test {
#Mock
private EntityManager em;
#Before
public void setUp(){
MockitoAnnotations.initMocks(this);
Mockito.reset(em);
}
//your junits
}
Of course you can. You use #Mock, that's all. #InjectMocks is for the service which uses EntityManager, not for EntityManager. And #Autowired is for real instanciation and injection via context, which only exists in an integrated test, not in an unit test, as what you do here.
Just use #Mock.
Related
I'm running into an issue where a unit test that extends HibernateSpec is failing due to the sessionFactory not being injected into the service under test. Whenever a method on the sessionFactory is called during the test, I get a NullPointerException (e.g. java.lang.NullPointerException: Cannot invoke method getClassMetadata() on null object) and the test subsequently fails.
I'm using Grails 3.2.4 and Hibernate 5.
This was working when the test used #TestMixin(HibernateTestMixin), but it looks like with some updates, the mixin is deprecated and suggests using HibernateSpec instead.
Here's a snippet from my test:
class TestDatabaseServiceSpec extends HibernateSpec {
def setup() {
}
def cleanup() {
}
void "test method"() {
when:
service.method()
then:
true
}
}
And here is a snippet from the service under test:
void method() {
...
TABLE_NAMES.add(sessionFactory.getClassMetadata('MyDomain').tableName)
...
}
I have tried to set service.sessionFactory in setup method as well as setupSpec method with the sessionFactory available in the test, but that did not help unfortunately. I have thought about using an integration test, but I would really like to see if I can continue to have this unit test work as it was before. Does anyone know if I am I doing something incorrectly or if there is a workaround/solution for this?
Thank you!
Viewing source code of HibernateSpec could give some hint. Could be there is no getSessionFactory() method in Hibernate 5 grails plugin that you are using.
I am using org.grails.plugins:hibernate5:6.0.6 with grails 3.2.5 and sessionFactory is not null for me in unit tests.
I understand that it is not always possible to upgrade, but it could give an idea what is the source of the problem.
Update:
service.sessionFactory = sessionFactory
also must be called in test setup.
What worked for me was to add the annotation #FreshRuntime to the spec and to add a doWithSpring closure to the test that sets up the sessionFactory for me (i.e. sessionFactory(InstanceFactoryBean, sessionFactory, SessionFactory)). Also, I made sure to add both service.sessionFactory = sessionFactory and service.transactionManager = transactionManager to the setupSpec method. Finally, I needed to override getDomainClasses() to work with all of the domain objects I wanted to in the test. Thanks for all the help!
The Test Mixins have been deprecated for the new traits since 3.2.3.
https://docs.grails.org/latest/guide/testing.html
Since Grails 3.3, the Grails Testing Support Framework is used for all
unit tests. This support provides a set of traits.
However, I still find myself using HibernateSpec as I can get multiple Domain classes from that, and the ServiceUnitTest for the service as well. The HibernateSpec has the needed sessionFactory.
E.g.
class MyServiceSpec extends HibernateSpec implements ServiceUnitTest<MyService>{
List<Class> getDomainClasses() { [Tag, TagLink, TagLinkValue, TagValue, TestDomain] }
...
def setup() {
service.sessionFactory = sessionFactory
...
}
// tests here with all those domain classes available and the service
}
The DataTest allows for multiple domain classes, but not the service as well.
https://testing.grails.org/latest/guide/index.html#unitTestingDomainClasses
the service test allows for the service, but not multiple domain classes.
https://testing.grails.org/latest/guide/index.html#unitTestingServices
You could use both of them together, but neither one of them has the session factory (that I could see), I'm on Grails 4.0.1. I looked through Github code for the latest and still don't see it available. Plus, the DataTest doesn't a hibernate session, it uses a SimpleMap instead so you can't use hql with it, which I wanted.
My Service was using the statelessSession
def statelessSession = sessionFactory.openStatelessSession()
String queryString = "select DISTINCT(t.tagRef) from com.fmr.aps.taggable.TagLink t group by t.tagRef order by t.tagRef ASC"
Query query = statelessSession.createQuery(queryString)
query.setReadOnly(true);
ScrollableResults results = query.scroll(ScrollMode.FORWARD_ONLY);
So I needed a unit test trait or base class with it and I spent several hours trying to make the new traits give me what I wanted. Even I began subclassing the DataTest class to try and make it give me the sessionFactory, but eventually just went with the HibernateSpec and it's nice to be able to run that one test class with several Domains, the Service and the sessionFactory.
In our previous app we used StructureMap and we could write very little code.
before every service we added the dependencies like:
[SetterProperty]
public IXService XService { get; set; }
and in the constructor
ObjectFactory.BuildUp(this);
then in test we could instantiate it simply by
var service = new XService();
Now, we start another app and using asp.net core build-in DI container.
it look like we should write a lot of code, and very long constructor for each test:
private readonly ILogger<AccountsController> _logger;
private readonly IMapper _mapper;
private readonly IAccountBlService _accountBlService;
private readonly IValidationHelper _validationHelper;
private readonly IValidator<AccountDTO> _accountDTOValidator;
private readonly Example _example;
private readonly IConfiguration _configuration;
public AccountsController(BillingContext context, ILogger<AccountsController> logger, IMapper mapper, IAccountBlService accountBlService,
IValidationHelper validationHelper, IValidator<AccountDTO> accountDTOValidator, IOptions<Example> example, IConfiguration configuration)
{
_logger = logger;
_mapper = mapper;
_accountBlService = accountBlService;
_validationHelper = validationHelper;
_accountDTOValidator = accountDTOValidator;
_configuration = configuration;
_example = example.Value;
}
Is there a shorter way we didnt found? is one planned for the near future? should we use StructureMap instead the built-in container? or there are disadvantages for this? thanks!
Is there a shorter way we didnt found?
In short: No, not with the default container. But I recommend you read Dependency Injection in .NET by Mark Seemann (if you have then please ignore me saying this), because have you heard of "Composition Root"? IMHO the way you declared dependencies has the same amount of code, just scattered all over your code base. While you should really keep it in one place for maintainability.
Is one planned for the near future? Not that I know of, but really if you look at it, it's the same amount of code, just centralized. We however use NServiceBus's ability to call "RegisterComponents" on the BusConfiguration which uses reflection to register all dependencies in one call. You could look for containers that can do the same. Now if you're thinking about your tests, if you use XUnit you can set up your SUT via de test class's constructor. Refactor it in factory classes so you only have to write it once. This way you can also throw mocks in to keep your tests clean.
Should we use StructureMap instead the built-in container?
If you wish. We use Autofac.
Or are there disadvantages for this?
Not that we've encountered thus far. Sometimes you need the IServiceProvider for special 'tricks' but there's always a way.
Note: if you are concerned about having 7 dependencies in your controller (which is a lot indeed) there are a few options:
Look at the scope of the dependency. If it's only used in 1 or 2 action methods you can also declare it [FromService] in the action method's signature
Is your controller doing too much? Watch out for god classes. Maybe it needs refactoring. After all, controllers are nothing more than logical collections of action methods.
Can dependencies be combined? Sometimes it seems they need to be seperated, but in most contexts they are always in pairs. It appears there's a high cohesion and you could combine them in a helper class to maintain cohesion.
I use MVC,EF5 and three layer. (DAL,BLL,UI) I 've apply unit of work pattern to my project. And i want to resolve unit of work class every controller's request. And after execute i run commit method. I 've set ninject as following code. But it's create about 10 times. So My bll class raise different context error.
//i want to change this every controller request. I don't want to use InSingletonScope() because it be cause to dead lock etc..
_kernel.Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
//sample manager
public class BannerManager:IBannerService
{
private readonly IUnitOfWork _unitOfWork;
public BannerManager(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
}
I am not sure whether I understood the exact way of how these two does the injection using #Inject,but I recently developed an app where during the first phase of development I used Dependency Injection using #inject of HK2 and binded the resources using abstract binder,it worked fine.Then I wanted to inject one more value. I needed to inject a basic String values using #Inject and the value for this was got form a method annotated with #Produces.But when I do that I get this error.
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at Injectee(requiredType=String
I read in many places and many suggest CDI and HK2 have some issues working together.I am not able to resolve the issue.
When I try the above scenario in two different standalone programs they run fine.But when I integrate them I get the above error message.
This is what I found in java's jira:
https://java.net/jira/browse/GLASSFISH-20597
My example is:
public ClassA{
#Inject
ClassBInter b;
}
I binded the class b in the abstract binder
new AbstractBinder(){
#Override
protected void configure() {
//Binding the implementation to the interface
bind(ClassBImpl.class).to(ClassBInter.class);
}
}
this worked fine.
but when I tried the below concept of adding an #Inject to a String in the same system,it crashes with the above exception
public ClassC{
#Inject
String name;
}
Producer Class
public ProducerClass{
#Produces
public String getName(){
return "henry Ford";
}
}
String injection is generally not supported, across the board. You can use qualifiers, which should help with resolution.
Do you have a beans.xml file in your deployment?
Is there any way I can mock FormsAuthentication.Authenticate("username", "password") method with test credential? My test goal is to make sure that if authentication fails, it redirects to correct place. I'm using Rhino Mocks as mocking framework.
Thank you very much for your help,
Since you are using mvc, if you create a new project and look in the Account controller's code you will find the following clarification:
The FormsAuthentication type is sealed
and contains static members, so it is
difficult to unit test code that calls
its members. The interface and helper
class below demonstrate how to create
an abstract wrapper around such a type
in order to make the AccountController
code unit testable.
Below this, there are these declarations:
public interface IFormsAuthentication
public class FormsAuthenticationService : IFormsAuthentication
public interface IMembershipService
public class AccountMembershipService : IMembershipService
You may look for implementations in the referred code.
I don't use Rhino Mocks, but I think it is not possible to mock static methods with any .Net mocking framework except typemock. The best work around is to create an interfaced adapter around it.