<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Joshua Barton</title>
    <description>The latest articles on DEV Community by Joshua Barton (@foobartn).</description>
    <link>https://dev.to/foobartn</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F76686%2Fd81349fd-3ce7-4f3c-bcc4-e0b46895b2eb.jpg</url>
      <title>DEV Community: Joshua Barton</title>
      <link>https://dev.to/foobartn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/foobartn"/>
    <language>en</language>
    <item>
      <title>C# Testing With User Secrets</title>
      <dc:creator>Joshua Barton</dc:creator>
      <pubDate>Tue, 03 Mar 2020 13:00:00 +0000</pubDate>
      <link>https://dev.to/foobartn/c-testing-with-user-secrets-36l3</link>
      <guid>https://dev.to/foobartn/c-testing-with-user-secrets-36l3</guid>
      <description>&lt;h2&gt;
  
  
  TLDR
&lt;/h2&gt;

&lt;p&gt;Use ConfigurationBuilder, AddUserSecrets, and IConfiguration.GetValue("key") to get access to User Secrets from any .Net Core project. No complex procedure required! And minimal scarring!*&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;*These claims have not been evaluated by any legitimate agency. Read at your own risk.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Problem
&lt;/h2&gt;

&lt;p&gt;"Don't push sensitive material to the source code repository."&lt;/p&gt;

&lt;p&gt;Most developers are pretty familiar with this. Obviously, we don't want our precious keys and passwords escaping into The Wild Wild Web and falling prey to some nefarious basement dwelling evil-doer named DarkCLIde. &lt;em&gt;Obviously&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;With Unit Testing this isn't a problem. Unit Tests are done in "a vacuum" of sorts. The entire purpose of a Unit Test is to rely on as few dependencies as possible and test one single "Unit" or function at a time.&lt;/p&gt;

&lt;p&gt;But what about Integration Testing?&lt;/p&gt;

&lt;p&gt;You know, the practice of making sure things that work separately also work &lt;em&gt;together&lt;/em&gt;. That way you don't end up with something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WBntj0AJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.foobarton.com/images/twounitnointegration.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WBntj0AJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.foobarton.com/images/twounitnointegration.gif" alt="Two Unit Tests No Integration"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But when interacting with different live systems you usually need credentials of some sort: an API key, a username and password, etc. So where do you put them? &lt;/p&gt;

&lt;p&gt;You could use a file that you add to your .gitignore settings. But then your teammates have to make sure they do that too -- and that no one accidentally forgets. Because rewriting Git history &lt;strong&gt;sucks&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  User Secrets
&lt;/h2&gt;

&lt;p&gt;With .Net Core you can use what are known as User Secrets. Since introduction this has been fairly easy to implement if you want to build an ASP.NET Core web application. ASP.NET Core does all the work for you.&lt;/p&gt;

&lt;p&gt;But what if you built a library? Maybe one that interacts with an API? How do you get the User Secrets working? Luckily, with one of the more recent updates, they added "Manage User Secrets" to the context menu of more than just ASP.NET Core projects. This makes initial set up much easier!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can also use&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;dotnet user-secrets init&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
 from within the project directory if you're not using Visual Studio.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now you have all the necessary bits in place. What's next? This can be a little confusing since the documentation for User Secrets only refers to ASP.NET Core -- and for that you don't need to do anything else to get it working except add data to your secrets file. &lt;/p&gt;

&lt;p&gt;But what about console applications and test projects?&lt;/p&gt;

&lt;h2&gt;
  
  
  .Net Core Library
&lt;/h2&gt;

&lt;p&gt;I'm going to focus on what an Xunit test project for a .Net Core Library would look like. Because it's the use case I came across that had very little documentation. Most of the examples I found had you build a whole ServiceCollection and set up Dependency Injection etc; and you could! But if you just want to use User Secrets, I can show you a much simpler way.&lt;/p&gt;

&lt;p&gt;Let's assume you've written a library for interacting with an API that looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyApi&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;MyApi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_apiKey&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; 

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;AddUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;// Code to add user here&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetUsers&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;// Code to get users here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Alright, so now how do we prove that, given an apiKey, AddUser actually adds a user? and GetUsers actually gets the user you added?&lt;/p&gt;

&lt;p&gt;Integration Tests.&lt;/p&gt;

&lt;p&gt;Keep in mind that at this level I'm not looking for efficiency. I don't care so much &lt;em&gt;how&lt;/em&gt; it works, only that &lt;em&gt;it works&lt;/em&gt;. i.e. The result is what I expect. So do your best to ignore how simplified and lacking in content the example code above is. &lt;/p&gt;

&lt;p&gt;Let's see the not-so-secure way first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserTests&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Fact&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;ShouldAddUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;myApi&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;MyApi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1580gskg023t83t0ig0s"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Bob"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;myApi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;myApi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetUsers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"Bob"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Should&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;BeTrue&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Assuming this library works the way we expect it to, this should result in a passing test. We added the user "Bob" and then checked to see that the user "Bob" was added. But now our API key is sitting there. Out in the open. For anyone with access to the code to see.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2BQlLoZK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.foobarton.com/images/dangerwillrobinson.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2BQlLoZK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.foobarton.com/images/dangerwillrobinson.gif" alt="Danger, Will Robinson! Danger!"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Using User Secrets
&lt;/h2&gt;

&lt;p&gt;How do we fix it? With a little re-&lt;strong&gt;Configuration&lt;/strong&gt;, of course. Let's assume this is the contents of our User Secrets file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ApiKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1580gskg023t83t0ig0s"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And now we'll modify our UserTests class to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserTests&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;_apiKey&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;UserTests&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;configuration&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ConfigurationBuilder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddUserSecrets&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;_apiKey&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetValue&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"ApiKey"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Fact&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;ShouldAddUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;myApi&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;MyApi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_apiKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Bob"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;myApi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;myApi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetUsers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"Bob"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Should&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;BeTrue&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That's it!&lt;/p&gt;

&lt;p&gt;So what have we done here? &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We've created a configuration so we could use the AddUserSecrets extension method.&lt;/li&gt;
&lt;li&gt;We used the configuration method for getting the value of the property "ApiKey", which was added from the User Secrets file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now when the ShouldAddUser() test runs, it will pull the _apiKey from the configuration a.k.a. your User Secrets file; a file which is outside the project path and so is in no danger of being checked in via source control. &lt;/p&gt;

&lt;p&gt;Result? No sensitive data uploaded! Groot Happy Dance Time!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VMPdW29N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.foobarton.com/images/dancinggroot.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VMPdW29N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.foobarton.com/images/dancinggroot.gif" alt="Dancing Groot"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>c</category>
      <category>net</category>
      <category>dev</category>
    </item>
  </channel>
</rss>
