--- layout: post title: "EnsureSuccessStatusCode as an assertion" description: "It finally dawned on me that EnsureSuccessStatusCode is a fine test assertion." date: 2020-09-28 5:50 UTC tags: [Unit Testing] --- {% include JB/setup %}
{{ page.description }}
Okay, I admit that sometimes I can be too literal and rigid in my thinking. At least as far back as 2012 I've been doing outside-in TDD against self-hosted HTTP APIs. When you do that, you'll regularly need to verify that an HTTP response is successful.
You can, of course, write an assertion like this:
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
If the assertion fails, it'll produce a comprehensible message like this:
Assert.Equal() Failure Expected: OK Actual: BadRequest
What's not to like?
The problem with testing strict equality in this context is that it's often too narrow a definition of success.
You may start by returning 200 OK
as response to a POST
request, but then later evolve the API to return 201 Created
or 202 Accepted
. Those status codes still indicate success, and are typically accompanied by more information (e.g. a Location
header). Thus, evolving a REST API from returning 200 OK
to 201 Created
or 202 Accepted
isn't a breaking change.
It does, however, break the above assertion, which may now fail like this:
Assert.Equal() Failure Expected: OK Actual: Created
You could attempt to fix this issue by instead verifying IsSuccessStatusCode:
Assert.True(response.IsSuccessStatusCode);
That permits the API to evolve, but introduces another problem.
What happens when an assertion against IsSuccessStatusCode
fails?
Assert.True() Failure Expected: True Actual: False
That's not helpful. At least, you'd like to know which other status code was returned instead. You can address that concern by using an overload to Assert.True
(most unit testing frameworks come with such an overload):
Assert.True( response.IsSuccessStatusCode, $"Actual status code: {response.StatusCode}.");
This produces more helpful error messages:
Actual status code: BadRequest. Expected: True Actual: False
Granted, the Expected: True, Actual: False lines are redundant, but at least the information you care about is there; in this example, the status code was 400 Bad Request
.
That's not bad. You can use that Assert.True
overload everywhere you want to assert success. You can even copy and paste the code, because it's an idiom that doesn't change. Still, since I like to stay within 80 characters line width, this little phrase takes up three lines of code.
Surely, a helper method can address that problem:
internal static void AssertSuccess(this HttpResponseMessage response) { Assert.True( response.IsSuccessStatusCode, $"Actual status code: {response.StatusCode}."); }
I can now write a one-liner as an assertion:
response.AssertSuccess();
What's not to like?
If you're already familiar with the HttpResponseMessage class, you may have been reading this far with some frustration. It already comes with a method called EnsureSuccessStatusCode. Why not just use that instead?
response.EnsureSuccessStatusCode();
As long as the response
status code is in the 200 range, this method call succeeds, but if not, it throws an exception:
Response status code does not indicate success: 400 (Bad Request).
That's exactly the information you need.
I admit that I can sometimes be too rigid in my thinking. I've known about this method for years, but I never thought of it as a unit testing assertion. It's as if there's a category in my programming brain that's labelled unit testing assertions, and it only contains methods that originate from unit testing.
I even knew about Debug.Assert, so I knew that assertions also exist outside of unit testing. That assertion isn't suitable for unit testing, however, so I never included it in my category of unit testing assertions.
The EnsureSuccessStatusCode
method doesn't have assert in its name, but it behaves just like a unit testing assertion: it throws an exception with a useful error message if a criterion is not fulfilled. I just never thought of it as useful for unit testing purposes because it's part of 'production code'.
The built-in EnsureSuccessStatusCode
method is fine for unit testing purposes. Who knows, perhaps other class libraries contain similar assertion methods, although they may be hiding behind names that don't include assert. Perhaps your own production code contains such methods. If so, they can double as unit testing assertions.
I've been doing test-driven development for close to two decades now, and one of many consistent experiences is this:
The code shown here is part of the sample code base that accompanies my book Code That Fits in Your Head.
Comments
Unfortunately, I can't agree that it's fine to use
EnsureSuccessStatusCode
or other similar methods for assertions. An exception of a kind different from assertion (XunitException
for XUnit,AssertionException
for NUnit) is handled in a bit different way by the testing framework.EnsureSuccessStatusCode
method throwsHttpRequestException
. Basically, a test that fails with such exception is considered as "Failed by error".For example, the test result message in case of 404 status produced by the
EnsureSuccessStatusCode
method is:Where "System.Net.Http.HttpRequestException :" text looks redundant, as we do assertion. This also may make other people think that the reason for this failure is not an assertion, but an unexpected exception. In case of regular assertion exception type, that text is missing.
Other points are related to NUnit:
- Failure: a test assertion failed. (Status=Failed, Label=empty)
- Error: an unexpected exception occurred. (Status=Failed, Label=Error)
See NUnit Common Outcomes. Thus `EnsureSuccessStatusCode` produces "Error" status instead of desirable "Failure".EnsureSuccessStatusCode
as assertion inside multiple asserts."assertions"
property gets into the test results XML file and might be useful. This property increments on assertion methods,EnsureSuccessStatusCode
- obviously doesn't increment it.Yevgeniy, thank you for writing. This shows, I think, that all advice is contextual. It's been more than a decade since I regularly used NUnit, but I vaguely recall that it gives special treatment to its own assertion exceptions.
I also grant that the "System.Net.Http.HttpRequestException" part of the message is redundant. To make matters worse, even without that 'prologue' the information that we care about (the actual status code) is all the way to the right. It'll often require horizontal scrolling to see it.
That doesn't much bother me, though. I think that one should optimise for the most frequent scenario. For example, I favour taking a bit of extra time to write readable code, because the bottleneck in programming isn't typing. In the same vein, I find it a good trade-off being able to avoid adding more code against an occasional need to scroll horizontally. The cost of code isn't the time it takes to write it, but the maintenance burden it imposes, as well as the cognitive load it adds.
The point here is that while horizontal scrolling is inconvenient, the most frequent scenario is that tests don't fail. The inconvenience only manifests in the rare circumstance that a test fails.
I want to thank you, however, for pointing out the issues with NUnit. It reinforces the impression I already had of it, as a framework to stay away from. That design seems to me to impose a lock-in that prevents you from mixing NUnit with improved APIs.
In contrast, the xunit.core library doesn't include xunit.assert. I often take advantage of that when I write unit tests in F#. While the xUnit.net assertion library is adequate, Unquote is much better for F#. I appreciate that xUnit.net enables me to combine the tools that work best in a given situation.
I see your point, Mark. Thanks for your reply.
I would like to add a few words in defense of the NUnit.
First of all, there is no problem to use an extra library for NUnit assertions too. For example, I like FluentAssertions that works great for both XUnit and NUnit.
NUnit 3 also has a set of useful features that are missing in XUnit like:
I can recommend to reconsider the view of NUnit, as the library progressed well during its 3rd version. XUnit and NUnit seem interchangeable for unit testing. But NUnit, from my point of view, provides the features that are helpful in integration and UI testing.
Yevgeniy, I haven't done UI testing since sometime in 2005, I think, so I wasn't aware of that. It's good to know that NUnit may excel at that, and the other scenarios you point out.
To be clear, while I still think I may prefer xUnit.net, I don't consider it perfect.


Write it down
This page is a demo that shows everything you can do indie portfolio blog posts.
Personal is the prefect theme for developers, designers and other creatives
This page is a demo that shows everything you can do indie portfolio blog posts.
This page is a demo that shows everything you can do indie portfolio blog posts.


Welcome to our survey form. We promise to be confidential with your personal data. We don't spam!
Gender
What do you like about our services?


visa
Businessmodel of Visa
Customer Segments
Visa has a multi-sided business model, with two interdependent customer segments that are both needed in order to operate:
- Consumers: This segment consists of individuals. They use Visa-branded debit, pre-paid, and/or credit cards given to them by issuer banks to pay for products and services from merchants.
- Merchants: This segment consists of businesses. They accept payment from consumers in the form of their various cards and submit them to acquirer banks for processing. ### Value Proposition
Visa offers three primary value propositions: convenience, accessibility, and brand/status.
The company’s payment cards make life easier. Specifically, they enable consumers to obtain money from their bank accounts without having to actually go in their branches; they can just use ATMs. The cards also allow them to make payments to merchants without having cash on hand.
The company also increases accessibility through its products. It offers a variety of payment card types. Consumers can use debit cards to access bank funds; pre-paid cards if they don’t have a bank account; and credit cards when they need to delay payment.
The company is one of the earliest payment card providers, and thus is one of the most well-known. It connects consumers and merchants in more than 200 countries worldwide and conducts 150 million transactions per day. It has been consistently ranked as the most trusted card firm.
Channels
Visa’s main channel is its website, through which it markets its products and services. However, the company also promotes itself through offline advertising on television and through marketing campaigns such as sponsored events. In addition, it offers a mobile app for consumers.
Customer Relationships
Visa’s customer relationship is primarily of a self-service, automated nature. Consumers use its cards and merchants accept them as payment, all while having limited interaction with employees. Also, its website features a “Resource” section providing detailed answers to frequent questions.
That said, there is a personal assistance component as it maintains customer service staff for providing assistance when needed.
Key Activities
Visa’s key activities focus on platform management. The company’s business model entails maintaining a common platform between three parties: consumers, merchants, and banks.
Key Partners
Visa has two key partners in its business. It works with issuer banks to distribute its payment card products to consumers. It also works with acquirer banks to accept and process payment transaction information submitted by merchants.
Key Resources
Visa’s main resource is its processing infrastructure. It utilizes several synchronized processing centers, including two data centers in the United States. These centers analyze payment transaction information and help ensure uninterrupted connectivity for consumers, merchants, and banks.
The company also relies heavily on its customer service staff to assist all involved parties as needed.
Cost Structure
Visa has a cost-driven structure, aiming to minimize expenses through significant automation. Its biggest cost driver is personnel expenses, a fixed cost, as it depends heavily on its human resources. Other major drivers are marketing, administrative, and network/processing expenses, all fixed costs.
Revenue Streams
Visa has four revenue streams, which are as follows:
- Service revenues: These are revenues obtained for providing financial institutions with support services for the delivery of Visa payment products and solutions to consumers.
- Data processing revenues: These are revenues obtained for authorization, clearing, settlement, network access, and other maintenance and support services that facilitate transaction and information processing among banks.
- International transaction revenues: These are revenues obtained for cross-border transaction processing and currency conversion activities.
- Other revenues: These are revenues generated through license fees for usage of the Visa brand; Visa Europe; account holder service fees; licensing and certification; and other activities.


wifi_off
Network disconnected!
We are sorry, unitl now our version of loly work online only
We hope add offline features in next version


CSS is the language for describing the presentation of Web pages, including colors, layout, and fonts. It allows one to adapt the presentation to different types of devices, such as large screens, small screens, or printers.
HTML, HyperText Markup Language, gives content structure and meaning by defining the content. HTML is used with headings, paragraphs, or images.
JavaScript is a an object-oriented computer programming language commonly used to create interactive effects within web browsers.
Python is a popular programming language. It was created by Guido van Rossum, and released in 1991. It is used for web development(server-side), software development, mathematics and system scripting.
Bootstrap, originally named Twitter Blueprint, was developed on August 19, 2011 by Mark Otto and Jacob Thornton at Twitter as a framework to encourage consistency across internal tools. Before Bootstrap, various libraries were used for interface development, which led to inconsistencies and a high maintenance burden.


ListItemFormatter
@objc(LNListItemFormatter)
public class ListItemFormatter : Formatter, NSSecureCoding
ListItemFormatter can be used to format variable-length lists of things in a locale-sensitive manner, such as “Monday, Tuesday, Friday, and Saturday” (in English) versus “lundi, mardi, vendredi et samedi” (in French).
-
The following constants specify predefined format modes for list items.
The mode is used in conjuction with the
See moreStyle
to pick the most appropriate set of patterns used by the formatter. You can read more about the patterns in the Unicode documentation.Declaration
Swift
@objc(LNListItemFormatterMode) public enum Mode : Int
-
The style is used in conjuction with the
See moreMode
to pick the most appropriate set of patterns used by the formatter. You can read more about the patterns in the Unicode documentation.Declaration
Swift
@objc(LNListItemFormatterStyle) public enum Style : Int
-
The format mode of the receiver.
The default value is set to
.standard
.Declaration
Swift
@objc public var mode: Mode
-
The format style of the reciever.
The default value is set to
.default
.Declaration
Swift
@objc public var style: Style
-
The locale for the receiver.
The default value is set to
Locale.autoupdatingCurrent
.Declaration
Swift
@objc public var locale: Locale
-
The default text attributes used to display the output string.
The value of this property is used by the receiver to produce the output
NSAttributedString
object ofListItemFormatter.attributedString(from:)
.The default value is an empty dictionary.
Declaration
Swift
@objc public var defaultAttributes: [NSAttributedString.Key : Any]
-
The item specific attributes used to display the list items within the output string.
The value of this property is used by the receiver to produce the output
NSAttributedString
object ofListItemFormatter.attributedString(from:)
, specifically by applying these attributes only to the items within thelist
array. These attributes are applied on top ofdefaultAttributes
.The default value of this property is an empty dictionary.
Declaration
Swift
@objc public var itemAttributes: [NSAttributedString.Key : Any]
-
Returns a string representation of the given list items formatted using the receiver’s current settings.
Declaration
Swift
@objc(stringFromList:) public func string(from list: [String]) -> String
Parameters
list
The list items to be formatted into a localised, human readable list.
Return Value
A string representation of
list
formatted using the receiver’s current settings. -
Returns an attributed strign representation of the given list items formatted using the receiver’s current settings.
The receiver uses the values set in its
defaultAttributes
anditemAttributes
properties by first applying the default attributes to the entire string and then addingitemAttributes
to the range of each item withinlist
. This means that attributes in the default attributes will first be applied to thelist
item ranges and then will be overwritten with values from the item specific attributes if they conflict. This means that you do not need to set the same attributes twice.Declaration
Swift
@objc(attributedStringFromList:) public func attributedString(from list: [String]) -> NSAttributedString
Parameters
list
The list items to be formatted into an attributed, localised, human readable list.
Return Value
An attributed string representation of
list
formatted using the receiver’s current settings.


David N. Udoumoh(
@draregem
)
BIO-DATA
HOBBIES/INTERESTS
CONTACT FORM
DATE OF BIRTH:
19.09.76
STATE OF ORIGIN:
AKWA IBOM
OCCUPATION:
MEDIA ENTREPRENEUR
HOMETOWN:
UYO
LIVE SOUND ENGINEERING
PHOTOGRAPHY
WEB DESIGN
UI/UK DESIGN