Dapper.SqlMapper.AddTypeHandler in unit tests (multithreaded) throws System.NotSupportedException, - dapper

I have built some SqlMapper type handlers for Dapper.
In my xunit unit tests I Add the type handler...
Dapper.SqlMapper.AddTypeHandler(new CustomTypeMappers.MyTypeHandler());
And make the dapper call, passing My custom type as a parameter of a stored procedure.
var data = new MyType(...);
IEnumerable<MyRecord> results = db.Query<MyRecord>("pTest_BinaryStream",
param: new
{
Data = data
},
commandType: CommandType.StoredProcedure);
When I execute all my unit tests together, I get an exception:
System.NotSupportedException : The member Data of type MyType cannot
be used as a parameter value
If I execute the unit tests one at a time it works fine. I suspect this has something to do with Dapper.SqlMapper and multi-threading, I'm just not sure what the proper approach would be.

Related

How would I configure Effort Testing Tool to mock Entity Framework's DbContext withOut the actual SQL Server Database up and running?

Our team's application development involves using Effort Testing Tool to mock our Entity Framework's DbContext. However, it seems that Effort Testing Tool needs to be see the actual SQL Server Database that the application uses in order to mock our Entity Framework's DbContext which seems to going against proper Unit Testing principles.
The reason being that in order to unit test our application code by mocking anything related to Database connectivity ( for example Entity Framework's DbContext), we should Never need a Database to be up and running.
How would I configure Effort Testing Tool to mock Entity Framework's DbContext withOut the actual SQL Server Database up and running?
*
Update:
#gert-arnold We are using Entity Framework Model First approach to implement the back-end model and database.
The following excerpt is from the test code:
connection = Effort.EntityConnectionFactory.CreateTransient("name=NorthwindModel");
jsAudtMppngPrvdr = new BlahBlahAuditMappingProvider();
fctry = new BlahBlahDataContext(jsAudtMppngPrvdr, connection, false);
qryCtxt = new BlahBlahDataContext(connection, false);
audtCtxt = new BlahBlahAuditContext(connection, false);
mockedReptryCtxt = new BlahBlahDataContext(connection, false);
_repository = fctry.CreateRepository<Account>(mockedReptryCtxt, null);
_repositoryAccountRoleMaps = fctry.CreateRepository<AccountRoleMap>(null, _repository);
The "name=NorthwindModel" pertains to our edmx file which contains information about our Database tables
and their corresponding relationships.
If I remove the "name=NorthwindModel" by making the connection like the following line of code, I get an error stating that it expects an argument:
connection = Effort.EntityConnectionFactory.CreateTransient(); // throws error
Could you please explain how the aforementioned code should be rewritten?
You only need that connection string because Effort needs to know where the EDMX file is.
The EDMX file contains all information required for creating an inmemory store with an identical schema you have in your database. You have to specify a connection string only because I thought it would be convenient if the user didn't have to mess with EDMX paths.
If you check the implementation of the CreateTransient method you will see that it merely uses the connection string to get the metadata part of it.
public static EntityConnection CreateTransient(string entityConnectionString, IDataLoader dataLoader)
{
var metadata = GetEffortCompatibleMetadataWorkspace(ref entityConnectionString);
var connection = DbConnectionFactory.CreateTransient(dataLoader);
return CreateEntityConnection(metadata, connection);
}
private static MetadataWorkspace GetEffortCompatibleMetadataWorkspace(ref string entityConnectionString)
{
entityConnectionString = GetFullEntityConnectionString(entityConnectionString);
var connectionStringBuilder = new EntityConnectionStringBuilder(entityConnectionString);
return MetadataWorkspaceStore.GetMetadataWorkspace(
connectionStringBuilder.Metadata,
metadata => MetadataWorkspaceHelper.Rewrite(
metadata,
EffortProviderConfiguration.ProviderInvariantName,
EffortProviderManifestTokens.Version1));
}

EasyMock 3.2: How to address public variables in a mocked class?

I'm trying to mock an open-source class. That class uses a number of public variables instead of get methods. I need to have the mocked class return another mocked class when that variable is accessed, but I'm not sure how. Here's an example:
SolrQueryRequest request = createNiceMock(SolrQueryRequest.class);
...
replay(request);
ResponseBuilder builder = createNiceMock(ResponseBuilder.class);
expect(builder.req).andReturn(request); // Throws exception
replay(builder);
The above example, however, throws the exception java.lang.IllegalStateException: no last call on a mock available on the builder.req line. Any idea how I can do this? Please note I don't have the option of refactoring the mocked classes.
Well, after playing around with it more I discovered it was pretty easy:
myBuilder.req = request;
Now when my class under test accesses the myBuilder.req variable, it is correctly set to my mocked SolrQueryRequest.

Register ResourceLocator with Autofac for WPF Application.Current

So to get around unit testing Application.Current, I created a ResourceLocator referenced from this. This would, if I can figure out how to register it in Autofac, allow me to inject the resource which would allow me to unit test without the worry of Application.Current being null. My question is how can i register this locator in autofac without autofac actually creating a new instance of the app? The appliaction.current is already created for us so I don't want autofac injecting another instance of the Application into my viewmodels. Something like:
container.RegisterType<ResourceLocator>().As<IResourceLocator>().SingleInstance();
Yes this will return a single instance but I think autofac will sill try to create an instance in the very beginning. Any help is greatly appreciated.
Overlooking the fact that requiring Autofac and Application.Current means you are integration testing and not unit testing, you can see from running this test that Autofac does not appear to generate a new value for Application.Current
[Test]
public void RegisterResolver()
{
//Arrange
Application expected = Application.Current;
var mainBuilder = new ContainerBuilder();
mainBuilder.RegisterType<ResourceLocator>()
.As<IResourceLocator>()
.SingleInstance();
IContainer container = mainBuilder.Build();
//Act
IResourceLocator test1 = container.Resolve<IResourceLocator>();
IResourceLocator test2 = container.Resolve<IResourceLocator>();
//Assert
Assert.That(test1, Is.EqualTo(test2));
Assert.That((test1 as ResourceLocator).application, Is.EqualTo(expected));
Assert.That((test2 as ResourceLocator).application, Is.EqualTo(expected));
}
However, if you do want more control you can use the Register method to define the initialiser for the instance you want to be used.
mainBuilder.Register(c => new ResourceLocator(Application.Current))
.As<IResourceLocator>()
.SingleInstance();

Test Function in MVC Project

So I want to test one of my Functions in my Web Project, but it's not actually connected to anything in the project yet (someone else is working on that part). The Function takes in an "ID" field, goes off and does some queries and gets some data, performs some calculations on it, and then writes a bunch of lines to a FileStream and returns that stream. I pretty much just want to test it by having it write the file to my own computer locally, and working with that file directory after the Function completes.
So my question is mainly:
1) How do I call this Function just for testing purposes so I can test all the queries/calculations/File writes, etc without it being connected to another part of the application just yet.
2) How can I change the 'Return fs' for the FileStream to write to my own computer locally to view the file that has been written.
Thanks guys!
To make your function testable you need to isolate all your dependencies and replace them in your test with stubs mocks. You can achieve this by wrappers around the file system classes and making sure your data layers classes have interfaces. With this your code could look like:
public class Something
{
IDataProvider provider;
IFileSystem fileSystem;
public Something(IDataProvider provider, IFileSystem fileSystem)
{
this.provider = provider;
this.fileSystem = fileSystem;
}
void DoThing(int id)
{
// make database call to get data
var data = provider.GetData(id);
fileSystem.Write("someFilePath",data);
}
}
With this you can write a test as such (in this casing using Moq like syntax):
void SomeTest()
{
var mockDataProvider = new Mock<IDataProvider>();
var mockFileSystem = new Mock<IFileSystem>();
var something = new Something(mockDataProvider.Object, mockFileSystem.Object);
var data = "someData";
mockDataProvider.Setup(x => x.GetData(5)).Return(data);
DoThing(5);
mockFileSystem.Verify(x => x.Write("someFilePath",data);
}
You need to read up on Unit Testing as this solves your problem in so many ways - it would also introduce you to dependency injection and mocking, which would be a great way to handle your problem.
Here is an overview...
Set up your class so it accepts the data-access and file-writer in the constructor. You can then pass in mock or stub version of the data access and file writer so you don't physically need to connect to a database or write to the file system to test your code.
In the "real world" you pass in the genuine data access and file writer.
In "test world" you use something such as MOQ or Rhino Mocks to create a pretend version of the data access, this means you can predict what will come back from the data access every time you test as it isn't the real database, it's some data you have prepared. You can also create a pretend file-writer that doesn't actually need to write a real file.
You can then test your class in isolation.
Dependency Injection:
http://msdn.microsoft.com/en-us/magazine/cc163739.aspx
Moq
http://code.google.com/p/moq/

method returning value appears as void in silverlight

I have written a webmethod that returns the list of the Users althought the service works fine, when I call it from the page the methods in the webservice have return type as void.
What you might be thrown off by is that web service calls in Silverlight must be handled asynchronously.
When you define a WebMethod, say for example you have one called DoWork on a Class called WorkMan. Your code in the Silverlight would end up looking like:
WorkManSoapClient client = new WorkManSoapClient();
client.DoWorkCompleted += new EventHandler<DoWorkCompletedEventArgs>(this.DoWorkCompleteHandler); // where DoWorkCompletedHandler handles the callback.
Then you call your actual method and allow the callback to process the result.
client.DoWorkAsync();
If your webmethod returns a value, your EventArg object will have a Result property that you can leverage for the result.
One final note: a personal stylistic thing but I like lambda expressions rather than generating a whole new method for the callback. I might write something like the following:
WorkManSoapClient client = new WorkManSoapClient();
client.DoWorkCompleted += (s,e) => {
if(e.Result != null){
object foo = e.Result;
}
};
client.DoWorkAsync();

Resources