We have recently upgraded to MvvMCross 6.2.2 and noticed we had to change to use Mvx.IoCProvider.
We have found that if we are constructing an MvxAsyncCommand in a ViewModel this causes a null reference exception on all unit tests that call this constructor
*
Result StackTrace:
at MvvmCross.Commands.MvxCommandBase..ctor()
at MvvmCross.Commands.MvxAsyncCommand..ctor(Func`1 execute, Func`1 canExecute, Boolean allowConcurrentExecutions)
at App.Mobile.Core.ViewModels.TestViewModel..ctor(IMvxNavigationService navigation, ITestService encService, ILogger logger)
at App.Mobile.Core.UnitTests.TestViewModelTests.<TestViewModel_Prepare>d__1.MoveNext()
*
Looking at the source in github the problem is due to Mvx.IocProvider being null.
public MvxCommandBase()
{
if (!Mvx.IoCProvider.TryResolve<IMvxCommandHelper>(out _commandHelper))
_commandHelper = new MvxWeakCommandHelper();
var alwaysOnUIThread = MvxSingletonCache.Instance == null || MvxSingletonCache.Instance.Settings.AlwaysRaiseInpcOnUserInterfaceThread;
ShouldAlwaysRaiseCECOnUserInterfaceThread = alwaysOnUIThread;
}
A fix has been implemented in the "develop" branch but this isn't available on nuget.
public MvxCommandBase()
{
// fallback on MvxWeakCommandHelper if no IoC has been set up
if (!Mvx.IoCProvider?.TryResolve(out _commandHelper) ?? true)
_commandHelper = new MvxWeakCommandHelper();
// default to true if no Singleton Cache has been set up
var alwaysOnUIThread = MvxSingletonCache.Instance?.Settings.AlwaysRaiseInpcOnUserInterfaceThread ?? true;
ShouldAlwaysRaiseCECOnUserInterfaceThread = alwaysOnUIThread;
}
Does anyone know of a workaround to initialize this IoCProvider within our unit test projects.
As you can see here the IoCProvider is resolved by getting the singleton of IMvxIoCProvider
public static IMvxIoCProvider IoCProvider => MvxSingleton<IMvxIoCProvider>.Instance;
So all you have to do is to initialize the IMvxIoCProvider.
As an example you can use this test, so in order to initialize it, you have to do:
MvxSingleton.ClearAllSingletons(); // This should be done in the test to clear all references of previous tests if necessary.
var instance = MvxIoCProvider.Initialize();
HIH
Related
I have the next JUnit test, and it works fine, but finally in the verify it throws expectation failure. I think it is because the mocked PsPort is different of the PsPort that I send to the DataReader.
Is there any other way to test it?
#Test
public void testguardarMensaje() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, InstantiationException{
String datoTest = "1=123456";
Constructor<PsPort> constructor = PsPort.class.getDeclaredConstructor(new Class[] {String.class});
constructor.setAccessible(true);
PsPort port = constructor.newInstance("middleware.conf");
PsPort drMock;
int hash1 = datoTest.hashCode();
String hashString1 = String.valueOf(hash1);
String combinedIdDataHashString1 = datoTest +"="+ hashString1;
drMock = strictMock(PsPort.class);
byte[] datoByte = port.encriptarDesencriptarMensaje(combinedIdDataHashString1.getBytes(), Cipher.ENCRYPT_MODE);
drMock.guardarDato(datoByte);
replayAll();
int hash = datoTest.hashCode();
String hashString = String.valueOf(hash);
String combinedIdDataHashString = datoTest +"="+ hashString;
byte[] datoByte2 = port.encriptarDesencriptarMensaje(combinedIdDataHashString.getBytes(), Cipher.ENCRYPT_MODE);
DatagramPacket paquete = new DatagramPacket(datoByte2,datoByte2.length);
paquete.getData();
DataReader dr = new DataReader(port, null, 100, "=", "C:/Users/Asier/Desktop/logs/");
dr.guardarMensaje(paquete, port);
verifyAll();
}
It is really confusing that you have two port objects. What is the sense of creating a mocked drPort; when you are then giving a "real" port object to your class under test?
You see: you either create a mock and pass that down to your code under test (and then you have to setup the mock for the expected behavior; which you can afterwards verify); or you only provide "real" objects to your code under test, but then you would normally do some kind of asserts on the results of calls to "code under test".
So, in that sense, it doesn't really matter that there is at least one problem in your code:
drMock.guardarDato(datoByte);
replayAll();
There should be a call to EasyMock.expectLastCall() after the method invocation on drMock; but as said: as the mocked object isn't really used, that doesn't matter, on the one hand. Because, if you added that statement, your test would always fail; since your un-used mock would never see the calls that you specified it to see.
In order to give you some guidance; this is how you do such kind of testing in general:
SomeClassYouNeed mockedThingy = createStrict/Nice(SomeClassYouNeed.class);
expect(mockedThingy.foo()).andReturn("whatever");
mockedThingy.bar();
expectLastCall();
replay (mockedThingy);
ClassUnderTest underTest = new ClassUnderTest(mockedThingy);
underTest.doSomething();
verify(mockedThingy)
Meaning: any "object" that
a) your "class under test" needs to do its work
b) you want/have to "control" in a certain way
needs to be mocked; including a "specification" of all expected method calls.
Then you provide the mocked things to your code under test; execute the method you want to test ... to finally verify that the mock saw the behavior that you specified for it.
I implemented a mock ExecutorService to return the result instantly without the need to create threads:
public static ExecutorService createMock() throws Exception {
ExecutorService executorServiceMock = EasyMock.createMock(ExecutorService.class);
Future future = EasyMock.createMock(Future.class);
Capture<Callable<?>> callableCapture = new Capture<>();
EasyMock.expect(executorServiceMock.submit(EasyMock.<Callable<?>>capture(callableCapture))).andReturn(future).anyTimes();
EasyMock.expect(future.get()).andAnswer(() -> callableCapture.getValue().call()).anyTimes();
executorServiceMock.shutdown();
EasyMock.expectLastCall().anyTimes();
EasyMock.replay(future, executorServiceMock);
return executorServiceMock;
}
The problem is that it always returns the same [mocked] Future object. I need to return the new instance of Future mock based on the callable object passed to executorServiceMock.submit()
I tried to use PowerMock.expectNew(Future.class) but it complained "No constructor found in class 'java.util.concurrent.Future' with parameter types: [ ]"
First of all "Don't mock type you don't own!". By link you may find several reasons why you shouldn't do it.
But, if you really want to do it, then replace return mock via answer witch will create a new nock each time:
EasyMock.expect(executorServiceMock.submit(EasyMock.<Callable<?>>capture(callableCapture))).andAnswer(() -> {
Future future = EasyMock.createMock(Future.class);
EasyMock.expect(future.get()).andAnswer(() -> callableCapture.getValue().call()).anyTimes();
EasyMock.replay(future);
return future;
}).anyTimes();
By the way, you cannot expected PowerMock.expectNew(Future.class) because Futureis interface and cannot be created.
The capture will always return the last captured object. In your case, you seem to want to synchronize the submission and the get.
So, I think you should do the following:
ExecutorService executorServiceMock = createMock(ExecutorService.class);
expect(executorServiceMock.submit(EasyMock.<Callable<?>>anyObject()))
.andAnswer(() -> {
Future future = createMock(Future.class);
Object value = ((Callable<?>) getCurrentArguments()[0]).call();
expect(future.get()).andReturn(value);
replay(future);
return future;
})
.anyTimes();
executorServiceMock.shutdown();
expectLastCall().anyTimes();
replay(executorServiceMock);
return executorServiceMock;
Below code fixed my issue.
#Mock
private ThreadPoolExecutor executorPool;
Future<String> result = CompletableFuture.completedFuture("S3PATH");
when(executorPool.submit(Mockito.<Callable<String>> anyObject())).thenReturn(result);
When using Castle.Facilities.AutoTx facility with [Transaction(TransactionScopeOption.RequiresNew)] attribute, the expected new System.Transactions.CommittableTransaction is not created.
You can easily test it with the following unit test
using System.Transactions;
using Castle.Facilities.AutoTx.Testing;
using Castle.MicroKernel.Registration;
using Castle.Transactions;
using Castle.Windsor;
using NUnit.Framework;
namespace Castle.Facilities.AutoTx.Tests
{
public class TransService
{
private readonly NewTransService _s2;
public TransService(NewTransService s2)
{
_s2 = s2;
}
[Transaction]
public virtual string DoInTrans()
{
var currentTransaction = System.Transactions.Transaction.Current;
Assert.That(currentTransaction != null, "The current transaction mustn't be null.");
string transId = currentTransaction.TransactionInformation.LocalIdentifier;
_s2.DoInNewTrans(transId);
return transId;
}
}
public class NewTransService
{
[Transaction(TransactionScopeOption.RequiresNew)]
public virtual string DoInNewTrans(string parentTransId)
{
var currentTransaction = System.Transactions.Transaction.Current;
Assert.That(currentTransaction != null, "The current transaction mustn't be null.");
string transId = currentTransaction.TransactionInformation.LocalIdentifier;
Assert.AreNotEqual(parentTransId, transId, "Ambient transaction must differ from parent");
return transId;
}
}
public class SingleThread_NewAmbient
{
private WindsorContainer _Container;
[SetUp]
public void SetUp()
{
_Container = new WindsorContainer();
_Container.AddFacility<AutoTxFacility>();
_Container.Register(Component.For<TransService>());
_Container.Register(Component.For<NewTransService>());
}
[TearDown]
public void TearDown()
{
_Container.Dispose();
}
[Test]
public void Automatically_Starts_New_CommitableTransaction()
{
using (var scope = new ResolveScope<TransService>(_Container))
scope.Service.DoInTrans();
}
}
}
Am I misunderstanding the purpose of [Transaction(TransactionScopeOption.RequiresNew)] or is it a bug?
I have been digging into the Castle.Transactions source code and I was able to fix the behavior by changing following piece of code in Castle.Transactions.TransactionManager.ITransactionManager.CreateTransaction(ITransactionOptions transactionOptions):
if (activity.Count == 0)
tx = new Transaction(new CommittableTransaction(new TransactionOptions
...
to
if (activity.Count == 0 || transactionOptions.Mode == TransactionScopeOption.RequiresNew)
tx = new Transaction(new CommittableTransaction(new TransactionOptions
...
Can someone from Castle experts / owners check this?
Author here,
I think your code is great and would merge a PR with it if it doesn't break other tests. =)
The reason that RequiresNew isn't well supported is because it's in 99% of the cases an anti-pattern. You're after encapsulating your unit of work in a transaction; and your unit of work should correspond 1-1 with the business operation that should be consistent.
Now, if you have a transaction going on the current thread, like you'd have in your case if you need to use 'RequiresNew', then you're either after reading dirty data or spawning an unrelated transaction (from a business-operation perspective). Hence, you should be doing it in another thread.
Since transactions are 'ambient' and not explicit in the control flow in a programming language like C#, you're left with your 'call context slots' to save the transaction reference in; but from your code's point of view these don't exist; what you have are partial functions that only work in a transactional context. If you spawn a second transaction; how are you going to coordinate that with the current transaction? It's hard; and likely to lead to problems.
An aside
In other transactional systems, like geteventstore.com you get an explicit transaction identifier -- you have one in System.Transactions, too, but it's not explicit in the API/ABI/ADO.Net to the database, hence you can't use it the same way. With an explicit transaction identifier you can solve failures when it becomes 'in doubt', i.e. the 'generals problem'; you can't with System.Transactions. Instead you must mount the transaction MMC on the DTC in question and manually roll it back or forward.
I have some code that's using a custom filter provider to perform property injection using Windsor on my action filters in a WebAPI project.
I'm just upgrading it from WebAPI beta to WebAPI RC, and I have a method in my container registration that used to read:
container.Register(
Component
.For<IEnumerable<IFilterProvider>>()
.UsingFactoryMethod(
() => GlobalConfiguration.Configuration.ServiceResolver.GetFilterProviders()
)
);
This would allow me to get the 'default' collection of filter providers and pass that into my custom filter provider, which would in turn retrieve the filters from each default provider, inject any missing dependencies via property injection, and return the filter with dependencies resolved.
In ASP.NET WebAPI RC, the ServiceResolver is now DependencyResolver and no longer has a GetFilterProviders() method - what should I be using in its place?
EDIT: Right, the following registration syntax is working - as in, it's passing all the unit tests and doesn't appear to be leaking memory or anything - but I'm not sure that explicitly binding to the instance returned by the Services.FilterProviders() is a good idea...
var filterProviders = GlobalConfiguration.Configuration.Services.GetFilterProviders();
container.Register(
Component.For<IEnumerable<IFilterProvider>>().Instance(filterProviders),
Component.For<IFilterProvider>().ImplementedBy<WindsorFilterProvider>()
);
and, for the sake of completeness, the WindsorFilterProvider looks like this:
public class WindsorFilterProvider : IFilterProvider {
private readonly IWindsorContainer container;
private readonly IEnumerable<IFilterProvider> filterProviders;
public WindsorFilterProvider(IWindsorContainer container, IEnumerable<IFilterProvider> filterProviders) {
this.container = container;
this.filterProviders = filterProviders;
}
public IEnumerable<FilterInfo> GetFilters(HttpConfiguration configuration, HttpActionDescriptor actionDescriptor) {
var filters = filterProviders.SelectMany(fp => fp.GetFilters(configuration, actionDescriptor)).ToList();
foreach (var filter in filters) container.Inject(filter.Instance);
return filters;
}
}
I guess the question is - is this a good way of doing this, or is there a recommended approach that I should be using instead?
I have following testing code trying to get one instance for generic and other for special purpose.
[TestMethod]
public void Test_Name_And_Named_Instances()
{
//MyClass implemented IMyClass
MyClass genericInstance = new MyClass("generic");
MyClass specialInstance = new MyClass("special");
IWindsorContainer container = new WindsorContainer();
container.Register(Component.For(IMyClass).Instance(genericInstance));
container.Register(Component.For(IMyClass).Instance(specialInstance).Named("special"));
IMyClass genericOne = container.Resolve<IMyClass>();
IMyClass specialOne = container.Resolve<IMyClass>("special");
Assert.AreSame(genericOne, genericInstance); //true
Assert.AreNotSame(genericOne, specialOne); //false
}
I expect to get two different instances, but the result is both genericOne and specialOne points to same objec genericInstance.
Any idea?
This doesn't compile:
container.Register(Component.For(IMyClass).Instance(genericInstance));
Should be:
container.Register(Component.For<IMyClass>().Instance(genericInstance));
Other than that, the test passes for me (Windsor 2.5.2)
EDIT:
If you flip the registrations, the test fails. This is by design. When you resolve without an explicit name, you're saying "give me the default component for this service", which in Windsor is the first registered component for that service type, by default.
If you need different components under the same service type, assign explicit names to all of them when registering and resolving.