C# - Unit test method that raises event with Guid argument - c#

I'm trying to figure out how to test this scenario and coming up blank.
I have a listener service that will trigger the following when a file is detected in a mailslot:
IEventDispatcher _dispatcher;
IListener _mailslotListener;
public Service (IEventDispatcher dispatcher, IMailslotListener mailslotListener) {
_dispatcher = dispatcher;
_mailslotListener = mailslotListener;
}
public async void _Listener_OnFileDetected(object sender, MailslotArgs) {
string filePath = args.Message;
Directory.CreateDirectory(TempLocation);
FileId = Guid.NewGuid();
string tempPath = Path.Combine(TempLocation, FileId.ToString());
File.Move(filePath, tempPath);
await _dispatcher.DispatchEvent("documentPrinted", FileId);
}
This will move the file passed in to a temp location and rename it with a Guid. In my test, I'm trying to verify that the file was moved successfully, but I'm not sure how to access the Guid used and passed to the _dispatcher.DispatchEvent call.
I'm able to verify that the event was raised, but that's as far as I've gotten as the value being a random Guid seems to be an issue when asserting equality in the test.
[Test]
public void OnFileDetected_CallsDispatchEvent()
{
Directory.CreateDirectory(tempPath);
listenerService._Listener_OnFileDetected(null, new MailslotArgs(testFilePath));
mockEventDispatcher.Verify(m => m.DispatchEvent("fileDetected",
It.IsAny<Guid>()),
Times.Once);
}

This is a typical issue with static initializers. It's well known as the DateTime.Now variant, but the outcome is the same.
The problem is that, due to it's static nature, it's hard to mock the output of the method.
Since it's used within the implementation the outcome of the GUID is kept within, and there is no easy way to access it.
A common approach is to create a wrapper class + interface, to expose the Guid.NewGuid() method.
Using this approach you have full control over the Guid generation - you just need to use the appropriate class.
//The interface
public interface IGuidGenerator
{
Guid NewGuid();
}
//Use in the application
public class GuidGenerator: IGuidGenerator
{
public Guid NewGuid()
{
return Guid.NewGuid();
}
}
//Use in the test scenario
public class TestGuidGenerator: IGuidGenerator
{
public Guid NewGuid()
{
return new Guid("dddddddd-dddd-dddd-dddd-dddddddddddd");
}
}
If you are using an IoC framework, it would just be a matter of registering the interface and class, and pass the generator to the service:
public Service (IEventDispatcher dispatcher,
IMailslotListener mailslotListener,
IGuidGenerator guidGenerator)
{
_dispatcher = dispatcher;
_mailslotListener = mailslotListener;
_guidGenerator = guidGenerator;
}
The DateTime.Now variant, is actually commonly used as an interview question.
Here is some more on the subject: https://dvoituron.com/2020/01/22/UnitTest-DateTime/

Related

Saving data to multiple tables with dependency injection and maintaining transection in asp.net core app

I have simple classes to saves and get data (not like repository pattern). But while saving data to multiple tables I want to maintain a transaction. So I just went through Unit of work pattern, but that will require me to do a lot of changes. So I'm thinking if my approach will do the same as UOF.
Here's my code:
CalalogueRepository:
public interface ICalalogueRepository
{
void Create(string guid, string fileName);
}
public class CalalogueRepository : ICalalogueRepository
{
private CatalogueContext _catalogueContext;
public CalalogueRepository(CatalogueContext catalogueContext)
{
_catalogueContext = catalogueContext;
}
public void Create(string guid, string fileName)
{
_catalogueContext.Catalogues.Add(new Catalogue
{
CatalogueId = guid,
FileName = fileName
});
}
}
StuffRepo:
public interface IStuffRepo
{
void Create(string guid, List<StuffModel> myStuff);
}
public class StuffRepo : IStuffRepo
{
private CatalogueContext _catalogueContext;
public StuffRepo(CatalogueContext catalogueContext)
{
_catalogueContext = catalogueContext;
}
public void Create(string guid, List<StuffModel> myStuff)
{
//add stuff to _catalogueContext.StuffTable.Add
}
}
Finally a class that does the SaveChanges and Commit:
public class UOW : IUOW
{
private CatalogueContext _catalogueContext;
private ICalalogueRepository _calalogueRepo;
private IStuffRepo _stuffRepo;
public UOW(CatalogueContext catalogueContext,
ICalalogueRepository calalogueRepo,
IStuffRepo stuffRepo)
{
_catalogueContext = catalogueContext;
_calalogueRepo = calalogueRepo;
_stuffRepo = stuffRepo;
}
public void Save (string guid, string fileName, List<StuffModel> myStuff)
{
using (IDbContextTransaction transection = _catalogueContext.Database.BeginTransaction())
{
_calalogueRepo.Create(guid, fileName);
_stuffRepo.Create (guid, myStuff);
_catalogueContext.SaveChanges();
transection.Commit();
}
}
}
I think there is only 1 CatalogueContext throughout the call.
Ok, so as you can see here, AddDbContext is the right way to register it as you wrote in the comment on the question.
Here it says that AddDbContext will register the context as scoped.
And here you can find what scoped means.
Overall I think you are right that your code will use the same context throughout the Save method.
Couple thoughts:
Probably you want to have a try-catch in case an exception is thrown and you want to rollback
If you are not sure if it's working why not try it? You should test your code/application anyways.
Probably this could be done in a better way, but I don't have the context about the rest of your code/application, so I cannot tell. (Not sure what you mean by "...Unit of work pattern, but that will require me to do a lot of changes." for example.)
Now the Create methods not self-contained, meaning if you just want to add a new item to the table it is not enough to call Create, but separately call SaveChanges(). This is not an explicit problem, but has to be kept in mind and might be a little bit confusing for new developers on the project.

Akka.net deadlocking issue with ActorSelection

Having an issue with akka.net. I need to access an actor which I have already created with a specific name. I can retrieve the actor from IActorContext but I am struggling to access it from the ActorSystem.
I have created a method called GetOrCreateActor which attempts to get the actor using ActorSelection. If it doesn't exist, the catch creates a new actor with the name. If it does exist, I want it to return the reference. However, it never returns from '.Result'. Assuming this could be some sort of deadlocking issue.
public static IActorRef GetOrCreateActor<T>(this ActorSystem actorSystem, string actorPath, string name = null) where T : ActorBase
{
try
{
return actorSystem.ActorSelection(actorPath).ResolveOne(TimeSpan.FromSeconds(1)).Result;
}
catch
{
return actorSystem.ActorOf(actorSystem.DI().Props<T>(), name);
}
}
Edit
I've tried to include a simplified version of the calling code below.
The actor system is created in an IOC container using AutoFac (ExampleActor is the ReceiveActor I am trying to access):
containerBuilder.RegisterAssemblyTypes(typeof(ExampleActor).Assembly).Where(x => x.Name.EndsWith("Actor"));
var lazyContainer = new Lazy<IContainer>(() => containerBuilder.Build());
containerBuilder.Register(c =>
{
var system = ActorSystem.Create("ExampleActorSystem");
new AutoFacDependencyResolver(lazyContainer.Value, system);
return system;
}).As<ActorSystem>().SingleInstance();
return lazyContainer.Value;
ActorSystem is then injected into another class, where I call the GetOrCreateActor method (via the Execute method):
public class ExampleCommand : IExampleCommand
{
private readonly ActorSystem _actorSystem;
public ExampleCommand(ActorSystem actorSystem)
{
_actorSystem = actorSystem;
}
public void Execute()
{
SendMessage();
}
private void SendMessage()
{
string message = new Message();
_actorSystem.GetOrCreateActor<ExampleActor>("akka://ExampleActorSystem/user/ExampleActor", "ExampleActor").Tell(message);
}
}
The above command would be called from a RESTful endpoint
public ExampleGetModule(IExampleCommand exampleCommand)
{
Get["/api/createExample"] = parameters =>
{
exampleCommand.Execute();
};
}
Your deadlocking issue looks more like it has to do with how you're using your container than it does Akka.NET:
var lazyContainer = new Lazy<IContainer>(() => containerBuilder.Build());
containerBuilder.Register(c =>
{
var system = ActorSystem.Create("ExampleActorSystem");
new AutoFacDependencyResolver(lazyContainer.Value, system);
return system;
}).As<ActorSystem>().SingleInstance();
In terms of what can go wrong here, self-referential Lazy<T> types are an infamous source of race-conditions. You should not be calling lazyContainer.Value inside of this registration method if the output of containerBuilder.Build depends on the input of containerBuilder.Register.
Last thing is to use step-through debugging to make sure that your application actually calls into the ResolveOne method here - if you're not getting a timeout exception back then it means that your application is deadlocking on producing the actor system (because of how DI is configured).

Approach to test public methods depending on private methods

I'm trying to add tests to a legacy code, and as I start to adding code, I get the feeling that something is wrong.
In the following code, the public method RegisterChange is calling two private methods to:
Get the object to store
Store the object
public class ChangeService {
IRepository repository;
public ChangeService(IRepository repository){
this.repository = repository;
}
public bool RegisterChange( int entityId ){
var entity = GetParsedEntity( entityId );
SaveEntity( entity );
return true;
}
private Entity GetParsedEntity( int id ) {
var entity = repository.GetEntityById( id );
return new Entity{ Name = entity.Name };
}
private void SaveEntity( Entity entity ) {
repository.Save( Entity );
}
}
public class ChangeServiceFact(){
[Fact]
public void When_valid_entity__Should_save_entity(){
var mock = new Mock<IRepository>();
var service = new ChangeService(mock.object);
var result = service.RegisterChange( 0 );
Assert.True(result);
}
}
So, when Im mocking the repository, I had to go and check the private method's code to know which operations to mock.
The problem that I'm seeing with this approach is that, because the code is testing not only the test subject (the public method) but also the private methods, is not clear which should be the test result by looking at the test subject (public method).
In the case that, later on, someone decide to modify one private method (like throwing an exception from GetParsedEntity), the test will continue to pass correctly, but the client code could fail because of this change.
In this particular case, Im using C#, XUnit and Moq, but I think is more a general testing question.
The problem that I'm seeing with this approach is that, because the code is testing not only the test subject (the public method) but also the private methods, is not clear which should be the test result by looking at the test subject (public method).
The test subject you mention has no visible effect without knowing its full contract. What the full contract here is? The mentioned public method and constructor, which takes dependency. It's the dependency that's important here and interaction with this dependency is what should be tested. Private methods are (as always) implementation detail - irrelevant to unit testing.
Having said that, let's get back to the contract. What is the actual contract of test subject (ChangeService method)? To retrieve object from repository basing on some id, create different object and save the later in the same repository. And this is your test.
[Fact]
public void ChangeService_StoresNewEntityInRepository_BasedOnProvidedId()
{
const string ExpectedName = "some name";
var otherEntity = new OtherEntity { Name = ExpectedName };
var mock = new Mock<IRepository>();
var service = new ChangeService(mock.object);
mock.Setup(m => m.GetEntityById(0)).Return(otherEntity);
service.RegisterChange(0);
mock.Verify(m => m.SaveEntity(It.Is<Entity>(e => e.Name == ExpectedName));
}

Machine.Fakes how to test virtual method implementation?

Given I have a controller class as such:
public class ResourceController : AuthorizedController
{
public virtual string Resource()
{
//do magic
}
public virtual string ResourceParent()
{
var url = Resource();
return url;
}
}
}
With the test harness:
[Subject(typeof (ResourceController))]
public class When_I_want_the_parent_resource : WithSubject<ResourceController>
{
private static readonly string ParentUrl = "/organizations/1";
private static readonly string ResourceUrl = "/organizations/1/contacts/1";
private static string _result;
private Establish context = () =>
{
The<ResourceController>()
.WhenToldTo(x => x.Resource())
.Return(ResourceUrl);
};
private Because of = () => _result = Subject.ResourceParent();
private It should_match_the_expected_parent_url = () =>
_result.ShouldEqual(ParentUrl);
}
This unit test will fail because Subject.ResourceParent() will return null because Machine.Fakes has automocked this method. As a temporary workaround I just removed the virtual keyword from ResourceParent to be able to test my code. I assume there has to be a real solution for me to tell Machine.Fakes to not override ResourceParent()
actually there isn't a "real" solution in Machine.Fakes for this. I would argue that you need to reconsider you're fixture design.
First of all, as Tim already pointed out, you you should't fake any methods on the subject itself. Instead you should fake the dependencies of your controller and use your controller as-is in specifications. The intended usage of the "The" method is to access the dependencies of the subject under specification, but what you try in your spec is to access the subject itself. I think that's where things go wrong. The <ResourceController> and subject are actually separate instances. That's why you configured interaction doesn't happen.
Just some options to fix this in your code:
Introduce a new dependency in your code which you can stub via "The"
If the first seems to heavyweight, you could also replace the virtual method with a Func<string> dependency for your controller and use the "Configure" method to inject a specification specific one for your spec.
HTH,
Bjoern
If you're testing a controller, then perhaps you shouldn't be creating mocks or fakes of that controller. Otherwise you're just testing a mock and the test doesn't really have any validity.
Mock or fake the dependencies of the controller. Test the real controller.
In the end I ended up pulling this test out of Machine.Fakes and put it into a regular unit test. Then I just used Moq directly to configure the HttpRequestBase to seed data I needed and then just manually created my controller class and invoked methods on it.

Writing a testable "import data from database" class

I am tasked with pulling all the rows from a 3rd party vendor's SQLite data table, creating business objects from those records, and sending the new business objects off to another class.
Pseudo-code:
var databasePath = "%user profile%\application data\some3rdPartyVendor\vendor.sqlite"
var connection = OpenSqliteConnection(databasePath);
var allGizmoRecords = connection.Query(...);
var businessObjects = TransformIntoBizObjs(allGizmoRecords);
someOtherClass.HandleNewBizObjs(businessObjects);
I've got all that working.
My question is: How can I write this class so it's unit testable?
Should I:
use the repository pattern to mock out the data access
actually provide a dummy SQLite database in the unit test
Or any better ideas? I'm using C#, but this question seems rather language-agnostic.
You could inject a test-only Sqlite database quite easily, refactoring the code to look like below. But how are you asserting the results? The business objects are passed to someOtherClass. If you inject an ISomeOtherClass, that class's actions need to be visible too. It seems like a bit of pain.
public class KillerApp
{
private String databasePath;
private ISomeOtherClass someOtherClass;
public KillerApp(String databasePath, ISomeOtherClass someOtherClass)
{
this.databasePath = databasePath;
this.someOtherClass = someOtherClass;
}
public void DoThatThing()
{
var connection = OpenSqliteConnection(databasePath);
var allGizmoRecords = connection.Query(...);
var businessObjects = TransformIntoBizObjs(allGizmoRecords);
someOtherClass.HandleNewBizObjs(businessObjects);
}
}
[TestClass]
public class When_Doing_That_Thing
{
private const String DatabasePath = /* test path */;
private ISomeOtherClass someOtherClass = new SomeOtherClass();
private KillerApp app;
[TestInitialize]
public void TestInitialize()
{
app = new KillerApp(DatabasePath, someOtherClass);
}
[TestMethod]
public void Should_convert_all_gizmo_records_to_busn_objects()
{
app.DoThatThing();
Assert.AreEqual(someOtherClass.Results, /* however you're confirming */);
}
}
Using an IRepository would remove some of the code from this class, allowing you to mock the IRepository implementation, or fake one just for test.
public class KillerApp
{
private IRepository<BusinessObject> repository;
private ISomeOtherClass someOtherClass;
public KillerApp(IRepository<BusinessObject> repository, ISomeOtherClass someOtherClass)
{
this.repository = repository;
this.someOtherClass = someOtherClass;
}
public void DoThatThing()
{
BusinessObject[] entities = repository.FindAll();
someOtherClass.HandleNewBizObjs(entities);
}
}
[TestClass]
public class When_Doing_That_Thing
{
private const String DatabasePath = /* test path */;
private IRepository<BusinessObject> repository;
private ISomeOtherClass someOtherClass = new SomeOtherClass();
private KillerApp app;
[TestInitialize]
public void TestInitialize()
{
repository = new BusinessObjectRepository(DatabasePath);
app = new KillerApp(repository, someOtherClass);
}
[TestMethod]
public void Should_convert_all_gizmo_records_to_busn_objects()
{
app.DoThatThing();
Assert.AreEqual(someOtherClass.Results, /* however you're confirming */);
}
}
But this still feels quite cumbersome. There are two reasons, 1) the Repository pattern has been getting some bad press lately from Ayende, who knows a thing or two about Repository. And 2) what are you doing writing your own data access!? Use NHibernate and ActiveRecord!
[ActiveRecord] /* You define your database schema on the object using attributes */
public BusinessObject
{
[PrimaryKey]
public Int32 Id { get; set; }
[Property]
public String Data { get; set; }
/* more properties */
}
public class KillerApp
{
private ISomeOtherClass someOtherClass;
public KillerApp(ISomeOtherClass someOtherClass)
{
this.someOtherClass = someOtherClass;
}
public void DoThatThing()
{
BusinessObject[] entities = BusinessObject.FindAll() /* built-in ActiveRecord call! */
someOtherClass.HandleNewBizObjs(entities);
}
}
[TestClass]
public class When_Doing_That_Thing : ActiveRecordTest /* setup active record for testing */
{
private ISomeOtherClass someOtherClass = new SomeOtherClass();
private KillerApp app;
[TestInitialize]
public void TestInitialize()
{
app = new KillerApp(someOtherClass);
}
[TestMethod]
public void Should_convert_all_gizmo_records_to_busn_objects()
{
app.DoThatThing();
Assert.AreEqual(someOtherClass.Results, /* however you're confirming */);
}
}
The result is a much smaller class and a business object and data-layer that you can change more easily. And you don't even have to mock the database calls, you can configure and initialize ActiveRecord to use a test database (in-memory, even).
Well, the only thing that would really need to be tested here is TransformIntoBizObjs, I would think, since the connection code should have been written/tested elsewhere. Simply passing things that might show up to Transform and seeing if the right thing pops out would be what you need to do.
Remember to test all usecases of Transform, even potentially weird items that probably shouldn't end up in the function call, but might. Never know what people have been shoving in their databases.
Inversion of Control (IoC) and Dependency Injection (DI) will go a long way towards making your code more testable. There are a lot of frameworks out there that can assist you with this, but for your purposes you don't necessarily need to go to all that effort.
Start with extracting an interface that might look something like this:
Interface ISqlLiteConnection
{
public IList<GizmoRecord> Query(...);
}
Once you've done that, you should refactor the OpenSqlLiteConnection() method to return an instance of ISqlLiteConnection, rather than the concrete implementation. To test, just create a class that implements your interface, which mocks up the actual DB queries and connections with determinate results.
Databases are complicates, you need to test your query code and you need to test it against a real sqlite instance - otherwise you can't be sure you didn't hit some rare sqlite quirk or bug.
And since the only way to test your query is to run it on a real sqlite file, and it's really easy to include such a file with your test there's no point to adding another layer just to make it "more" testable or to have "pure" unit tests.
Just make sure to add all the strange edge cases you can think of to your sample file.

Categories