0 Comments

When using Entity Framework for a project I needed to be able to mock the database context and sets in order to do unit testing. I was able to find some ways to mock the Entity Framework context, but I did not find a complete solution. Most examples did not take into account setting the identity column or deleting items. In order to handle these scenarios I created my own MockDbSet.

I will demonstrate how this works with a sample project for creating and editing reminders.

 

The context is represented by a simple interface:

public interface IRemindersContext
{
IDbSet<Reminder> Reminders { get; set; }

Task<int> SaveChangesAsync();
}

 

The business logic is in a manager class that takes the context interface as a parameter to enable dependency injection and unit testing:

public class ReminderManager : IReminderManager
{
IRemindersContext _context;
public ReminderManager(IRemindersContext context)
{
_context = context;
}

public List<Reminder> Get()
{
return _context.Reminders.ToList();
}

public Reminder Get(int reminderId)
{
return _context.Reminders.Find(reminderId);
}

public async Task<Reminder> Add(string description)
{
var reminder = new Reminder { Description = description };

_context.Reminders.Add(reminder);

await _context.SaveChangesAsync();

return reminder;
}

public async Task<bool> Delete(int reminderId)
{
var reminder = _context.Reminders.Find(reminderId);

_context.Reminders.Remove(reminder);

var result = await _context.SaveChangesAsync();

return result > 0;
}
}

 

In order to do unit testing of the business logic I need to be able to mock the IDbSet. This is where my mock class comes in. I am using Moq to do create the mocks. The mock IDbSet will be created by a static method on a static class. The method will accept a generic list containing the data that should be returned by the mock IDbSet. The class and method look like this:

public static class MockDbSet
{
public static Mock<IDbSet<T>> CreateMockDbSet<T>(List<T> data) where T : class
{
...
}
}

 

The first thing I need to do is to set up the mock to behave like an IQueryable<T>. To do this I will create the mock object mock some of the IQueryable methods.

var mock = new Mock<IDbSet<T>>();
var queryData = data.AsQueryable();
mock.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryData.Provider);
mock.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryData.Expression);
mock.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryData.ElementType);
mock.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(queryData.GetEnumerator());

 

This is all that is needed in order to create a mock that will allow you to select items from it. I want to have add and remove functionality so I need to add those methods to my mock. First, I will find the primary key by using the class name with the suffix “Id”.

Type type = typeof(T);
string colName = type.Name + "Id";
var pk = type.GetProperty(colName);
if (pk == null)
{
colName = type.Name + "ID";
pk = type.GetProperty(colName);
}

Note: Before using the pk you must validate that it is not null.

 

Now that I have the primary key and I create a method to add new items to the mock IDbSet and return them with the new ID. My implementation supports integer and Guid primary keys.

mock.Setup(x => x.Add(It.IsAny<T>())).Returns((T x) =>
{
if (pk.PropertyType == typeof(int)
|| pk.PropertyType == typeof(Int32))
{
var max = data.Select(d => (int)pk.GetValue(d)).Max();
pk.SetValue(x, max + 1);
}
else if (pk.PropertyType == typeof(Guid))
{
pk.SetValue(x, Guid.NewGuid());
}
data.Add(x);
return x;
});

 

The code for remove is much simpler:

mock.Setup(x => x.Remove(It.IsAny<T>())).Returns((T x) =>
{
data.Remove(x);
return x;
});

 

I also need to support Find for my application. This turns out to be the trickiest method to implement. The difficult part is determining the primary key column and using it in a LINQ statement. I already know the primary key column so I will reuse that variable to write the query to find the item. To do this I create an expression tree to build the lambda expression that matches the given value to the primary key.

mock.Setup(x => x.Find(It.IsAny<object[]>())).Returns((object[] id) =>
{
var param = Expression.Parameter(type, "t");
var col = Expression.Property(param, colName);
var body = Expression.Equal(col, Expression.Constant(id[0]));
var lambda = Expression.Lambda<Func<T, bool>>(body, param);
return queryData.FirstOrDefault(lambda);
});

 

Here is the complete code for the MockDbSet:

public static class MockDbSet
{
public static Mock<IDbSet<T>> CreateMockDbSet<T>(List<T> data) where T : class
{
var mock = new Mock<IDbSet<T>>();
var queryData = data.AsQueryable();
mock.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryData.Provider);
mock.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryData.Expression);
mock.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryData.ElementType);
mock.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(queryData.GetEnumerator());

Type type = typeof(T);
string colName = type.Name + "Id";
var pk = type.GetProperty(colName);
if (pk == null)
{
colName = type.Name + "ID";
pk = type.GetProperty(colName);
}
if (pk != null)
{
mock.Setup(x => x.Add(It.IsAny<T>())).Returns((T x) =>
{
if (pk.PropertyType == typeof(int)
|| pk.PropertyType == typeof(Int32))
{
var max = data.Select(d => (int)pk.GetValue(d)).Max();
pk.SetValue(x, max + 1);
}
else if (pk.PropertyType == typeof(Guid))
{
pk.SetValue(x, Guid.NewGuid());
}
data.Add(x);
return x;
});
mock.Setup(x => x.Remove(It.IsAny<T>())).Returns((T x) =>
{
data.Remove(x);
return x;
});
mock.Setup(x => x.Find(It.IsAny<object[]>())).Returns((object[] id) =>
{
var param = Expression.Parameter(type, "t");
var col = Expression.Property(param, colName);
var body = Expression.Equal(col, Expression.Constant(id[0]));
var lambda = Expression.Lambda<Func<T, bool>>(body, param);
return queryData.FirstOrDefault(lambda);
});
}

return mock;
}
}

 

In order to use this in unit tests I will create a mock context class that I can create an instance of for each unit test.

public static class RemindersContextMock
{
public static Mock<IRemindersContext> GetMockContext()
{
var context = new Mock<IRemindersContext>();

context.Setup(c => c.Reminders).Returns(GetReminders().Object);

return context;
}

public static Mock<IDbSet<Reminder>> GetReminders()
{
var reminders = new List<Reminder>
{
new Reminder { ReminderId = 1, Description = "Do work" },
new Reminder { ReminderId = 2, Description = "Read a book" },
new Reminder { ReminderId = 3, Description = "Make dinner" }
};

return MockDbSet.CreateMockDbSet<Reminder>(reminders);
}
}

I will create a setup method for my unit tests where I create the instance of the manager class to test and pass in my mocked context.

ReminderManager _manager;
Mock<IRemindersContext> _context;

[SetUp]
public void SetUp()
{
_context = RemindersContextMock.GetMockContext();

_manager = new ReminderManager(_context.Object);
}

Now I can write tests for the methods in the manager class. First I will verify that I can get the list of reminders from the context.

[Test]
public void CanGetReminders()
{
var reminders = _manager.Get();
Assert.AreEqual(3, reminders.Count());
}

Next I will verify that when I add a reminder it gets a valid ID.

[Test]
public async Task CanAddReminder()
{
var reminder = await _manager.Add("Walk the dog");
Assert.AreEqual(4, reminder.ReminderId);
}

Finally I will test the remove method to ensure that it is removing the reminder from the context.

[Test]
public async Task CanDeleteReminder()
{
var reminder = _manager.Get().FirstOrDefault(r => r.Description == "Read a book");
await _manager.Delete(reminder.ReminderId);
var reminder2 = _manager.Get(reminder.ReminderId);
Assert.IsNull(reminder2);
}

I hope this helps you if you need to create a mock IDbSet. It should be clear now how to add to the mock DbSet’s methods if you need additional functionality.

0 Comments

Sometimes I need to do the same thing repeatedly as a part of my normal work tasks. For example, if I need to query a database using a list of strings I might need to escape all the strings in the list. LINQPad allows me to easily write some C# to do that and save the code to use again later. I will demonstrate this using my example of preparing a list of strings for a database query.

I might be given this list of ingredients and I need to use them in a SQL query.

flour

vinegar

eggs

sugar

cornmeal

I can write some C# code in LINQPad to take a string, split it at each newline, then combine it separating the values with commas.

StringToSQLINQuery

Now I can easily get the values I was given ready for a SQL query.

StringToSQLINQueryRan

So that I don’t have to write the same code again next time I will save it to my LINQPad queries folder.

StringToSQLINQuerySave

Now I can access that same code again next time easily.

StringToSQLINQuerySavedQueries

That’s all I have to do and I have a quick and easy way to do something repetitive. LINQPad is a great utility for small coding tasks.

0 Comments

While creating a health check page for a service I realized that I was repeating code that timed each health check method. On the health check page there are several methods and each is responsible for checking one thing. The methods all return the same object which is defined by this class:

public class HealthStatus
{
public bool Status { get; set; }
public long RequestTimeMs { get; set; }
public string ErrorMessage { get; set; }
//other properties
}

I decided to refactor the code so that I was not repeating the same code over and over. The style of programming I have been learning from functional programming gave me an idea of how to refactor the code in a much simpler way than I would have without using a functional approach. I created this method which takes a method, starts a timer, runs the method, then puts the time it took to run in the return value.

public HealthStatus TimedHealthCheck(Func<HealthStatus> f)
{
var sw = new Stopwatch();
sw.Start();

var result = f();

result.RequestTimeMs = sw.ElapsedMilliseconds;

return result;
}

Now I can just wrap the work inside my health check methods with this and it will do the timing for me. Here is an example:

public HealthStatus CanParseString()
{
return TimedHealthCheck(() =>
{
var health = new HealthStatus
{
Status = false
};

try
{
var parseInt = 0;
health.Status = int.TryParse("123", out parseInt);
}
catch (Exception ex)
{
health.ErrorMessage = ex.Message;
}

return health;
});
}

To run the health checks I create a list and add each health check:

var healthChecks = new List<HealthStatus>();
healthChecks.Add(CanParseString());

0 Comments

I wanted to be able to publish events from my SmartThings devices to Azure Event Hub. Once I am publishing the events to Event Hub I will be able to save the data or take actions in real time based on the incoming data. In this post I will walk through setting up and Event Hub in Azure and publishing events to it using a Smart App that I will write. 

Creating an Azure Event Hub

To set up your Event Hub in Azure go to the Azure Management Portal and click the new button at the bottom. Then click on App Services, Service Bus, Event Hub, Quick Create.

EventHubCreate_thumb7

This will create an Event Hub under the Service Bus Section in the Portal. You will need the URL to connect to the Event Hub and you will need to set up access rules. You will also need to create an SAS token to access the Event Hub from the SmartThings App. See my previous post for details on how to do this.

Creating a SmartThings App

Log in to the SmartThings Developer site and click the green New SmartApp button.

Fill in the required fields. In the Settings section create EventHubSecret and EventHubURL settings. Put your SAS token and your Event Hub URL in these.

smartappsettings_thumb5

Click Create and you will be taken to the web IDE for the SmartApp.

Register for events from your devices

The first section of the app is the definition. These settings are populated by what you entered while creating the app.

The next section is the preferences section. This is where you tell SmartThings which sensors you wish to use in your app and you can specify names for them. I have several sensors I will use so I have set it up for power, light, motion, etc. You can also group related sensors by using a Section.

preferences {
section("Power Meter") {
input "powers", "capability.powerMeter", title: "Power Sensor", multiple: true
}
section("Environment") {
input "temperatures", "capability.temperatureMeasurement", title: "Temperature Sensors", multiple: true
input "lightMeters", "capability.illuminanceMeasurement", title: "Light Sensors", multiple: true
input "humidityMeters", "capability.relativeHumidityMeasurement", title: "Humidity Sensors", multiple: true
}
section("Security Sensors") {
input "motions", "capability.motionSensor", title: "Motion Sensors", multiple: true
input "contacts", "capability.contactSensor", title: "Contact Sensors", multiple: true
}
}

In the initialize section you can subscribe to events from your devices.

def initialize() {
subscribe(powers, "power", powerHandler)
subscribe(temperatures, "temperature", temperatureHandler)
subscribe(motions, "motion", motionHandler)
subscribe(contacts, "contact", contactHandler)
subscribe(lightMeters, "illuminance", illuminanceHandler)
subscribe(humidityMeters, "humidity", humidityHandler)
}

Sending events to the Event Hub

The next thing that we need to do is to create the method that will send data to the Event Hub. Data will be sent to the Event Hub with a POST to the Event Hub URL. SmartThings does this with the httpPost method. This method takes an object that contains the parameters for the post.

The url is the Event Hub URL. The body will be a json object containing the data about the event. You can send any data you want in the body. I am sending the sensor ID, name, type, and the value of the sensor. The content type and the request content type must be defined because the Event Hub returns a different content type than the body content type. Finally, the Authorization header must be set using the SAS token that was created for the Event Hub.

def sendEvent(sensorId, sensorName, sensorType, value) {
log.debug "sending ${sensorId} at ${value}"
def cleanedSensorId = sensorId.replace(" ", "")
def params = [
uri: "${appSettings.EventHubURL}",
body: "{ sensorId : \"${cleanedSensorId}\", sensorName : \"${sensorName}\", sensorType : \"${sensorType}\", value : \"${value}\" }",
contentType: "application/xml; charset=utf-8",
requestContentType: "application/atom+xml;type=entry;charset=utf-8",
headers: ["Authorization": "${appSettings.EventHubSecret}"],
]

try {
httpPost(params) { resp ->
log.debug "response message ${resp}"
}
} catch (e) {
//seems to think 201 is an error
//log.error "something went wrong: $e"
}
}

The Event Hub returns a 201 Created http status code. This causes an exception to be thrown. The error log is commented out for this reason, but while getting the app running it may be beneficial to uncomment it.

 

The final step is to create the event handlers that will use this method to send data to the event hub. For events that have a numeric value such as the power meter I am just sending the value directly to the event hub.

def powerHandler(evt) {
sendEvent('powerMeter', evt.displayName, 'power', evt.value)
}

For the events that contain a text value I am converting it for easier processing later.

def motionHandler(evt) {
if (evt.value == 'active') {
sendEvent(evt.displayName + 'motion', evt.displayName, 'motion', 'motion detected')
}
if (evt.value == 'inactive') {
sendEvent(evt.displayName + 'motion', evt.displayName, 'motion', 'no motion detected')
}
}

Here is the code for all of my event handlers:

def powerHandler(evt) {
sendEvent('powerMeter', evt.displayName, 'power', evt.value)
}

def temperatureHandler(evt) {
sendEvent(evt.displayName + 'temp', evt.displayName, 'temperature', evt.value)
}

def motionHandler(evt) {
if (evt.value == 'active') {
sendEvent(evt.displayName + 'motion', evt.displayName, 'motion', 'motion detected')
}
if (evt.value == 'inactive') {
sendEvent(evt.displayName + 'motion', evt.displayName, 'motion', 'no motion detected')
}
}

def contactHandler(evt) {
if (evt.value == 'open') {
sendEvent(evt.displayName + 'contact', evt.displayName, 'doorOpen', 'open')
}
if (evt.value == 'closed') {
sendEvent(evt.displayName + 'contact', evt.displayName, 'doorOpen', 'open')
}
}

def illuminanceHandler(evt) {
sendEvent(evt.displayName + 'light', evt.displayName, 'lumens', evt.value)
}

def humidityHandler(evt) {
sendEvent(evt.displayName + 'humidity', evt.displayName, 'humidity', evt.value)
}

Run the app and verify it is working

Everything is ready to run now. On the right side of the SmartApp IDE click Set Location and then set your sensors.

SmartAppSensors_thumb1

The headings and labels created in the SmartApp preferences will be shown. Each section will have virtual devices that can be controlled in the IDE for testing. I am just using my physical devices here.

After setting your sensors click on the Install button below the sensor settings. You should now be able to see log statements as events are sent.

Let the app run for at least 30 minutes and then check the Event Hub’s Dashboard in the Azure Management Portal. You should see a graph indicating that events are coming in and everything is working correctly.

EventHubDash_thumb1

0 Comments

I wanted to be able to publish events from an IoT application. I could not figure out how to create the SAS token in the language of the IoT application so I decided to just create one that would last for 90 days.

The first thing you will need is an Event Hub in Azure. Get the URL you are going to use for sending events. It should look like this:

https://youreventhub-ns.servicebus.windows.net/youreventhub/publishers/test01/messages

You will need to create a shared access policy that will allow you to send events to the Event Hub.

EventHubAccess

Then get the key from the policy.

image

The SAS token has several parts. This is the string we will use to generate it: "SharedAccessSignature sig=%s&se=%i&skn=%s&sr=%s". The first part is the signature, which we will create later. Then the expiration time, the key name used to generate the signature, and the URI encoded Event Hub URL.

The signature is generated by encrypting the combination of the URL and the expiration. It is encrypted using HMACSHA256. To do this we will create a function that takes the string to encrypt and the key and returns the encrypted string.

let encryptString (key : string) (message : string) =
 let keyBytes = System.Text.Encoding.UTF8.GetBytes(key)
 let messageBytes = System.Text.Encoding.UTF8.GetBytes(message)
 use hmac = new System.Security.Cryptography.HMACSHA256(keyBytes)
 let hashmessage = hmac.ComputeHash(messageBytes)
 Convert.ToBase64String(hashmessage)

 

The expiration is in Unix time so we need to convert the DateTime. I am creating a token that lasts for 90 days, but this could be changed to accept a parameter.

let toUnixTime (t : DateTime) =
    t.Subtract(new DateTime(1970, 1, 1)).TotalSeconds
 let expiry = DateTime.UtcNow.AddDays(90.0) |> toUnixTime |> Convert.ToInt32

We now have enough to create the method that creates the token.

let createToken (uri : string) keyName key =
 let toUnixTime (t : DateTime) =
    t.Subtract(new DateTime(1970, 1, 1)).TotalSeconds
 let expiry = DateTime.UtcNow.AddDays(90.0) |> toUnixTime |> Convert.ToInt32
 let encUri = System.Web.HttpUtility.UrlEncode(uri)
 let stringToSign = encUri + "\n" + expiry.ToString()
 let signature = encryptString key stringToSign |> System.Web.HttpUtility.UrlEncode
 sprintf "SharedAccessSignature sig=%s&se=%i&skn=%s&sr=%s" signature expiry keyName encUri

 

Call this method and pass in your Event Hub URI, key name, and key. This will provide you with an SAS token that will expire after 90 days.