1. Thomas Rolseth
  2. SnapObjects
  3. Friday, 2 August 2019 21:33 PM UTC

Has anyone created unit tests for a service in SnapDevelop using xUnit?  I have a simple test shown below which builds fine.  When I run the test I get the attached error.  Would love to see a working example from someone.  Given that the service method is returning a datastore I'm not sure how to use Assert in this instance.  

Thanks, Tom

 

        private readonly IOrderService _orderService;

        public OrderServiceTests(IOrderService OrderService)
        {
            _orderService = OrderService;
        }

        [Fact]
        public void Test_Orders()
        {

            var int id = 1;

            // Invoke the service method
            var result = _orderService.GetOrder(id);

            // Validate the result
            Assert.Empty(result);
        }

Attachments (1)
Logan Liu @Appeon Accepted Answer Pending Moderation
  1. Monday, 5 August 2019 08:12 AM UTC
  2. SnapObjects
  3. # 1

Hi Thomas,

It seems that your _orderService field has not been instantiated.

You can refer to my following sample (It reuses the same logic as the Web API project):

public class UnitTest1
    {
        private ServiceProvider _serviceProvider;
        private SampleDataContext _dataContext;

        public UnitTest1()
        {
            // Build Configuration
            var configuration = new ConfigurationBuilder()
                .AddJsonFile("appsettings.json")
                .Build();

            // Services
            var services = new ServiceCollection();

            // Add DataContext to Services
            services.AddDataContext(m => m.UseSqlServer(configuration["ConnectionStrings:Local"]));

            // Add ISampleService to Services
            services.AddScoped();

            // Build the service provider
            _serviceProvider = services.BuildServiceProvider();


            // Parse DWs
            DataObjectFactory.LoadDataWindow(null);

            // Get DataContext 
            _dataContext = _serviceProvider.GetService();
        }

        [Fact]
        public void TestService()
        {
            // Get service
            var service = _serviceProvider.GetService();

            // Test RetrieveOne method
            var ds = service.RetrieveOne(1);

            Assert.True(ds.RowCount > 0);
        }
    }

Regards,

Logan

Comment
There are no comments made yet.
Thomas Rolseth Accepted Answer Pending Moderation
  1. Monday, 5 August 2019 16:27 PM UTC
  2. SnapObjects
  3. # 2

My unit test project (Record_API.Test) has a dependency/link with my snapdevelop web api project (Record_API).  I shouldn't have to create a new configuration, a new service collection or a new datacontext, etc because that has been done already in the api project.  By doing 'using Record_API.Services;' in my test class I should have a reference/handle to the services in my api.

I tried what you suggested but it didn't work -- it couldn't find the appsettings file and several other lines of code did not resolve.  Can you look at my attached solution and offer some advice on how to get my test to work?

Thanks, Tom

Attachments (1)
Comment
There are no comments made yet.
Logan Liu @Appeon Accepted Answer Pending Moderation
  1. Tuesday, 6 August 2019 02:30 AM UTC
  2. SnapObjects
  3. # 3

Hi Thomas,


Sorry for my mistakes in the previous code.
Your unit test project (Record_API.Test) doesn't have the same program startup logic as the Web API project. It starts from [Fact] for each method to test. So you need to mock up the dependencies of your service (e.g.: the config file, the DataContext object, parsed DataWindows).

See attached. I reused the ServiceCollection to get the service, and you can also find better solutions to mock up them.
Refer to https://docs.microsoft.com/dotnet/core/testing/unit-testing-with-dotnet-test and https://docs.microsoft.com/aspnet/core/mvc/controllers/testing?view=aspnetcore-2.1 for more info.

Regards,
Logan

Attachments (1)
Comment
There are no comments made yet.
Thomas Rolseth Accepted Answer Pending Moderation
  1. Wednesday, 7 August 2019 20:38 PM UTC
  2. SnapObjects
  3. # 4

I was able to successfully run my tests using the changes you provided -- thanks!  I have since created another test and the code is below.  This test fails with an error message saying that the _dataContext parameter can't be null.  Since your example established a db connection in the definition/startup of my unit test class, why doesn't this work?

Tom

 

        [Fact]
        public void Test_Update_CP_Desc()
        {
            var dataStore = new DataStore("ds1", _dataContext);
            
            dataStore.Retrieve("9510");
            dataStore.SetItem(1, "cp_desc", "Test");
            dataStore.Update();

            var cpDesc = dataStore.GetItemString(1, "cp_desc");
            
            Assert.Equal("Test",cpDesc);
        }

Comment
There are no comments made yet.
Logan Liu Accepted Answer Pending Moderation
  1. Thursday, 8 August 2019 02:07 AM UTC
  2. SnapObjects
  3. # 5

It seems that your _dataContext hasn't been instantiated. You can create a new instance for _dataContext in the constructor of the test class.

XUnit creates a new instance of the test class for every test that is run. You can refer to https://xunit.net/docs/shared-context for more details about how to share context between tests.

Regards,

 

Comment
There are no comments made yet.
Thomas Rolseth Accepted Answer Pending Moderation
  1. Friday, 9 August 2019 13:30 PM UTC
  2. SnapObjects
  3. # 6

How would you script out the creation a new instance for _dataContext in the constructor of the test class?  I want to have a valid handle on _dataContext when I do something like this in a test:

var datastore = new Datastore("ds_test", _dataContext)

Comment
There are no comments made yet.
Logan Liu @Appeon Accepted Answer Pending Moderation
  1. Monday, 12 August 2019 00:40 AM UTC
  2. SnapObjects
  3. # 7

Hi Thomas,

1) You can use DI, which has been used in the previous example:

(For more info about DI, refer to https://docs.microsoft.com/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.1)

// Add DataContext to Services

services.AddDataContext(m => m.UseSqlServer(configuration["ConnectionStrings:Local"]));

// Get a a new created DataContext

_dataContext = _serviceProvider.GetService();

 

2) Or get a service instance directly by DI. (You only need to receive _dataContext in the constructor of the service class):

// Add ISampleService to Services

services.AddScoped();

// Add DataContext to Services

services.AddDataContext(m => m.UseSqlServer(configuration["ConnectionStrings:Local"]));

// Get service

var service = _serviceProvider.GetService();

 

3) You can also create a new DataContext object manually. Refer to https://www.appeon.com/support/documents/appeon_online_help/snapobjects/Working_with_Transactions_in_SnapObjects/index.html

E.g.:

var options = new SqlServerDataContextOptions(connectionString);

var context = new SqlServerDataContext(options)

Regards,

Logan

 

 

 

 

 

Comment
There are no comments made yet.
  • Page :
  • 1


There are no replies made for this question yet.
However, you are not allowed to reply to this question.