How to test soft deletion event listner without setting up NHibernate Sessions - unit-testing

I have overridden the default NHibernate DefaultDeleteEventListener according to this source: http://nhibernate.info/blog/2008/09/06/soft-deletes.html
so I have
protected override void DeleteEntity(
IEventSource session,
object entity,
EntityEntry entityEntry,
bool isCascadeDeleteEnabled,
IEntityPersister persister,
ISet transientEntities)
{
if (entity is ISoftDeletable)
{
var e = (ISoftDeletable)entity;
e.DateDeleted = DateTime.Now;
CascadeBeforeDelete(session, persister, entity, entityEntry, transientEntities);
CascadeAfterDelete(session, persister, entity, transientEntities);
}
else
{
base.DeleteEntity(session, entity, entityEntry, isCascadeDeleteEnabled, persister, transientEntities);
}
}
How can I test only this piece of code, without configuring an NHIbernate Session?

You could subclass your event listener in your test code and provide a public method with the same signature as DeleteEntity, which simply calls the protected base implementation of DeleteEntity.
Mock the other dependencies, call the public method in the testable class and verify DateDeleted has been set.

I'm fairly certain you will not be able to test this without a properly configured session. However, you could config Nhibernate to use for instance SQLite with some dummy data in your tests.

Related

Mvx.Resolve fails in unit tests

I'm currently trying to write unit tests for an android/ios application written in xamaring using mvvmcross. I've followed the instructions in the wiki and they do work well to the point when a service tries to change the ViewModel this way:
var viewDispatcher = Mvx.Resolve<IMvxViewDispatcher>();
viewDispatcher?.ShowViewModel(
new MvxViewModelRequest(typeof(HomeViewModel), null, null, MvxRequestedBy.Unknown));
The tests fail at the first line with Mvx.Resolve();. I assume this is down to registering the interfaces in the mock IoC container:
this.mockDispatcher = new MockDispatcher();
this.Ioc.RegisterSingleton<IMvxViewDispatcher>(this.mockDispatcher);
this.Ioc.RegisterSingleton<IMvxMainThreadDispatcher(this.mockDispatcher);
so Mvx cannot resolve then when called this way. Can this code be tested or is there any other possibility to change the ViewModel from the service?
I think your AdditionalSetup never gets called. You have to add the SetUp attribute to a setup method and call the Setup() of MvxIoCSupportingTest if you use nunit, else the respective attribute.
public abstract class MvxTestBase : MvxIoCSupportingTest
{
protected MockDispatcher mockDispatcher;
protected override void AdditionalSetup()
{
this.mockDispatcher = new MockDispatcher();
this.Ioc.RegisterSingleton<IMvxViewDispatcher>(this.mockDispatcher);
this.Ioc.RegisterSingleton<IMvxMainThreadDispatcher>(this.mockDispatcher);
}
[SetUp]
public virtual void SetupTest()
{
Setup();
}
}
Or you call it in each test as shown here: https://mvvmcross.com/docs/testing#section-test-class-declaration-and-setup

Mock SomeClass.getClassLoader() when called in method (Mockito / PowerMockito)

I have inherited some code that isn't tested and which loads a resource using a method like :
SomeClass.class.getClassLoader().getResource("somefile");
I've written the following test but there are 0 interactions with the Mock class loader I've created. Can anyone comment on whether this type of test is possible.
public enum SomeClass {
INSTANCE;
public boolean someMethod() {
URL pathToLicense = SomeClass.class.getClassLoader().getResource("somefile");
return false;
}
}
#Test
public void testLicenseWorkflow(){
ClassLoader cl = PowerMockito.mock(ClassLoader.class);
File f = new File("someFile");
assertTrue(f.exists());
logger.info(f.getCanonicalPath() );
when(cl.getResource("somefile")).thenReturn(f.toURL());
verify(cl).getResource("somefile");
assertTrue(SomeClass.INSTANCE.someMethod());
}
Update - Adding a resources via Classloader
I've also tried the following but the someMethod this doens't seem to work either
new URLClassLoader(((URLClassLoader) SomeClass.INSTANCE.getClass().getClassLoader()).getURLs()) {
#Override
public void addURL(URL url) {
super.addURL(url);
logger.info("Calling add URL");
}
}.addURL(f.toURI().toURL());
You are not passing cl to anything. You prepare a mock for a classloader but then proceed to load the resource with another classloader, the one that loaded SomeClass. That is why you have 0 interactions in your mock.
And about your first question, it is possible if somehow you pass your mocked classloader to the method that actually loads the resource. For example, something like
public boolean someMethod(Classloader loader) {
URL pathToLicense = loader.getResource("somefile");
return false;
}
But I have to say that IMO, this test is not very useful, you should be mocking your own components, not java classes. If your goal mocking the classloader is to inject a different file when testing, a better approach is to change your code to receive a Stream and inject a stream connected to the file in production and in testing inject a stream connected to an element in memory.
In other words, resources make for bad testing when they need to be changed at test time

PersistenceContextType.EXTENDED inside Singleton

We are using Jboss 7.1.1 in an application mostly generated by Jboss Forge, however we added a repository layer for all domain related code.
I was trying to create a Startup bean to initialize the database state. I would like to use my existing repositories for that.
My repositories all have an extended PersistenceContext injected into them. I use these from my View beans that are #ConversationScoped #Stateful beans, by using the extended context my entities remain managed during a conversation.
First I tried this:
#Startup
#Singleton
public class ConfigBean {
#Inject
private StatusRepository statusRepository;
#Inject
private ZipCode zipCodeRepository;
#PostConstruct
public void createData() {
statusRepository.add(new Status("NEW"));
zipCodeRepository.add(new ZipCode("82738"));
}
}
Example repository:
#Stateful
public class ZipCodeRepository {
#PersistenceContext(PersistenceContextType.EXTENDED)
private EntityManger em;
public void add(ZipCode zipCode) {
em.persist(zipCode);
}
....
}
This ends up throwing an javax.ejb.EJBTransactionRolledbackException on Application startup with the following message:
JBAS011437: Found extended persistence context in SFSB invocation call stack but that cannot be used because the transaction already has a transactional context associated with it. This can be avoided by changing application code, either eliminate the extended persistence context or the transactional context. See JPA spec 2.0 section 7.6.3.1.
I struggled finding a good explanation for this, and actually figured that since EJB's and their injection are handled by proxies all the PersistenceContext injection and propagation would be handled automatically. I guess I was wrong.
However, while on this trail of thought I tried the following:
#Startup
#Singleton
public class ConfigBean {
#Inject
private SetupBean setupBean;
#PostConstruct
public void createData() {
setupBean.createData();
}
#Stateful
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public static class SetupBean {
#Inject
private StatusRepository statusRepository;
#Inject
private ZipCode zipCodeRepository;
public void createData() {
statusRepository.add(new Status("NEW"));
zipCodeRepository.add(new ZipCode("82738"));
}
}
}
This does the trick. All I did was wrap the code in a Stateful SessionBean that is a static inner class of my Singleton bean.
Does anyone understand this behavior? Because while everything works now I'm still a bit estranged as to why it works this way.
A container-managed extended persistence context can only be initiated
within the scope of a stateful session bean. It exists from the point
at which the stateful session bean that declares a dependency on an
entity manager of type PersistenceContextType.EXTENDED is created, and
is said to be bound to the stateful session bean.
From the posted code, it seems ZipCodeRepository isn't itself stateful bean, but you're calling it from one such bean.
In this case, you are initiating PersistenceContextType.TRANSACTION from ConfigBean & propogates through ZipCodeRepository having PersistenceContextType.EXTENDED & it tries to join the transaction, hence the exception.
Invocation of an entity manager defined with PersistenceContext- Type.EXTENDED will result in the use of the existing extended
persistence context bound to that component.
When a business method of the stateful session bean is invoked, if the stateful session bean uses container managed transaction
demarcation, and the entity manager is not already associated with the
current JTA transaction, the container associates the entity manager
with the current JTA transaction and calls
EntityManager.joinTransaction. If there is a different persistence
context already associated with the JTA transaction, the container
throws the EJBException.
While in later case, you're creating a new transaction in SetupBean for each invocation with TransactionAttributeType.REQUIRES_NEW which is of extended type, as it's a stateful bean.
Therefore, adding SetupBean as stateful session bean initiating new transaction for each invocation & later calling ZipCodeRepository doesn't result in exception. ZipCodeRepository will join the same transaction as initiated by SetupBean.

Unit Testing, using properties to pass in an interface

Im reading "The art of unit testing" atm and im having some issues with using properties to pass in an interface. The book states the following: "If you want parameters to be optional, use property getters/setters, which is a better way of defining optional parameters than adding different constructors to the class for each dependency."
The code for the property example is as follows:
public class LogAnalyzer
{
private IExtensionManager manager;
public LogAnalyzer ()
{
manager = new FileExtensionManager();
}
public IExtensionManager ExtensionManager
{
get { return manager; }
set { manager = value; }
}
public bool IsValidLogFileName(string fileName)
{
return manager.IsValid(fileName);
}
}
[Test]
Public void
IsValidFileName_NameShorterThan6CharsButSupportedExtension_ReturnsFalse()
{
//set up the stub to use, make sure it returns true
...
//create analyzer and inject stub
LogAnalyzer log = new LogAnalyzer ();
log.ExtensionManager=someFakeManagerCreatedEarlier;
//Assert logic assuming extension is supported
...
}
When/how would i use this feature?? The only scenario i can think of (This is probably wrong!) is if i had two methods in one class,
Method1() retrieves the database connection string from the config file and contains some form of check on the retrieved string.
Method2() then connect to the database and returns some data. The check here could be that that returned data is not null?
In this case, to test Method1() i could declare a stub that implements the IExtensionManager Interface, where the stub has a string which should pass any error checks i have in method1().
For Method2(), i declare a stub which implements the interface, and declare a datatable which contains some data, in the stub class. id then use the properties to assign this to the private manager variable and then call Method2?
The above may be complete BS, so if it is, id appreciate it if someone would let me know and ill remove it.
Thanks
Property injection used to change object's behavior after it was created.
BTW your code is tight coupled to FileExtensionManager, which is concrete implementation of IExtensionManager. How you are going to test LogAnalyzer with default manager? Use constructor injection to provide dependencies to your objects - this will make them testable:
public LogAnalyzer (IExtensionManager manager)
{
this.manager = manager();
}

Should unit tests know about NHibernate?

I'm following on from a previous question. The answer I accepted involves using a generic IRepository to handle basic CRUD, wrapped with a domain specific IMovieRepository which delegates to the generic setup. A further detail involves having a WrapQueryInSession method on the generic IRepository:
IEnumerable<T> WrapQueryInSession(Func<ISession, IEnumerable<T>> query);
I was getting to implementation when I realized that this exposes the NHibernate ISession to consumers of the generic repository. NHibernate is otherwise fully contained in the IRepository implementation, but for that method signature.
This comes to the fore when I want to unit test MovieRepository, by having an IRepository, implemented in RepositoryFake, passed to the MovieRepository constructor:
protected override void BeforeEachTest()
{
_fixture = new MovieRepository(new RepositoryFake());
}
My test class has a private fake repository implementation:
private class RepositoryFake : IRepository<Movie>
{
...
public IEnumerable<Movie> WrapQueryInSession(Func<ISession, IEnumerable<Movie>> query)
{
...
}
...
}
The way this is set up, the test class, and any other consumer of an IRepository implementation, is made aware of the ISession from NHibernate, and thus NHibernate itself. This seems a case of a leaky abstraction.
Is there a better way to fully contain use of NHibernate within an IRepository implementation?
The idea from my answer to your previous question was that the generic IRepository is only known inside your infrastructure layer - it is not published outside of this. When you publish the ISession to the non-generic repositories they gain a very versatile interface, as they have access to the ISession for querying. The problem with not exposing the ISession is that your generic repository will either:
Limit your querying capabilities or
Have a whole host of different methods for querying (basically duplicating the interface of the ISession.
Seems a bit of a waste having NHibernate's querying interface hidden away inside a facade (which the generic Repository would be limited to).
IMO, if you choose nHibernate, you should leverage the power it gives you and live with the dependence through-out your infrastructure dll (including tests). Think of the generic IRepository interface as a helper interface to NHibernate to reduce the amount of duplicate code inside the repositories.
I agree with the principle that NHibernate should not be abstracted completely but I have found that the querying interface of NHibernate can be hidden away without too much hassle and that can happen by using Query objects.
Each query object should leverage the power the NHibernate provides (ISession, ICriteria, IQuery, etc) and can be executed by the implementation of the IRepository.
Having Query objects instead of methods in your repositories offers better testability and it would not require any references to NHibernate in your test classes.
Here is how the whole thing could look like:
public interface IRepository
{
ISession Session { get; }
TResult Query<TResult>(IQuery<TResult> query);
}
public class Repository : IRepository
{
public ISession Session
{
get { return /* Call the session factory to return an ISession */; }
}
public TResult Query<TResult>(IQuery<TResult> query)
{
return query.Execute(Session));
}
}
public interface IQuery<TResult>
{
TResult Execute(QueryContext context);
}
public abstract class Query<TResult> : IQuery<TResult>
{
public abstract TResult Execute(ISession session);
}
public class GetPeopleByName: IQuery<Person>
{
private readonly string _name;
public GetPeopleByName(string name)
{
_name = name;
}
public override IList<Person> Execute(ISeesion session)
{
var query = context.Session.CreateCriteria(typeof(Person))
.Add(Restrictions.Eq("Name", _name));
return query.List<Person>();
}
}
Then you can use the above like:
IRepository repository = /* Get somehow the implementation */
IList<Person> people = repository.Execute(new GetPeopleByName("Anna"));