Posted on 24/10/2023 16:06:18
Hi Karol,
In general your unit tests should only be testing your own code.
Otherwise, it's an integration test and then you should be testing on a complete environment with DW, files, database, etc.
In order to perform unit tests on your own scheduled task add-in you should try to isolate all the external dependencies (DW, files, database or any other external services and libraries).
There are several ways to do that, but an easy solution is to use a derived "proxy" test class for your scheduled task add-in (see below).
Alternatively you can use third party libraries like Moq or NSubstitute for mocking in your unit tests.
Note: You might run into some issues even if you don't call any services directly anywhere and thats because some properties/methods on our domain entities (Shop, Product, etc.) will call the services when needed.
There might be someone out there who can come up with a better solution, but this approach should work for most scenarios...
// This is an example implementation of a scheduled task add-in which is going to be used in production.
[AddInName("MyScheduledTaskAddIn"), AddInLabel("My scheduled task add-in"), AddInIgnore(false)]
public class MyScheduledTaskAddIn : BaseScheduledTaskAddIn
{
public sealed override bool Run()
{
List<Shop> shops = GetShops().ToList();
foreach (var shop in shops)
{
ProcessShop(shop);
SaveShop(shop);
}
return true;
}
// You can separate your own logic into smaller testable methods and call them in your unit tests, if you need to.
internal static void ProcessShop(Shop shop)
{
shop.Name = $"{shop.Id} {Guid.NewGuid()}";
}
// You can mock this method in your unit tests by creating a derived class and overriding this method
protected virtual void SaveShop(Shop shop)
{
Dynamicweb.Ecommerce.Services.Shops.Save(shop);
}
// You can mock this method in your unit tests by creating a derived class and overriding this method
protected virtual IEnumerable<Shop> GetShops()
{
return Dynamicweb.Ecommerce.Services.Shops.GetShops();
}
}
// This is an implementation which inherits from the actual add-in and can be used for testing.
public class TestMyScheduledTaskAddIn : MyScheduledTaskAddIn
{
// This is a property which you can set in your unit tests to pass in some test data
public IEnumerable<Shop> Shops { get; set; }
// You can pass in some test data in the constructor - or just set the property above
public TestMyScheduledTaskAddIn(IEnumerable<Shop> shops)
{
Shops = shops ?? Enumerable.Empty<Shop>();
}
protected override void SaveShop(Shop shop)
{
// Do something here if you want
// Otherwise you could verify that Shops have been updated as expected in your unit tests.
}
protected override IEnumerable<Shop> GetShops()
{
return Shops;
}
}
/ Morten