I updated the testing documentation to reflect this:

https://cwiki.apache.org/confluence/display/SHIRO/Testing

It should be reflected on http://shiro.apache.org/testing.html within
an hour or so.

Cheers,

Les

On Tue, Dec 7, 2010 at 10:00 AM, Les Hazlewood <[email protected]> wrote:
> Hi Tauren,
>
> Matt Brictson recently posted an even better way using mock objects.
> You can create a mock Subject instance (since Subject is an interface,
> this works great with frameworks like Easymock and Mockito) and mock
> what would happen during a security check.  Then you bind and unbind
> your mock to the thread as necessary.
>
> If you're using the AbstractShiroTest base class as shown in the
> testing.html documentation page, this is all you would have to do (for
> example, using JUnit 4 annotations and Easymock):
>
> import static org.easymock.EasyMock.*;
>
> public class MyTest extends AbstractShiroTest {
>
>   �...@test
>    public void testSomething() {
>        Subject subjectUnderTest = createNiceMock(Subject.class);
>        expect(subjectUnderTest.isAuthenticated()).andReturn(true);
>
>        //bind the Subject to the thread so SecurityUtils and
>        //other framework code will work:
>        setSubject(subjectUnderTest);
>
>        //execute your test logic
>    }
>
> }
>
> Note that your mock subject will remain bound to the thread for all
> tests in a class unless you call the clearSubject() method after each
> test.
>
> This can be done in a JUnit @After method for example:
>
> @After
> public void tearDownSubject() {
>    clearSubject();
> }
>
> Or, some people may want that to be the case for all tests.  You can
> mix and match this setup/teardown logic in each method manually or use
> the @Before and @After annotations as you see fit.  The
> AbstractShiroTest class will however unbind the Subject from the
> thread at the end of the test class execution because of the
> @AfterClass annotation in its tearDownShiro() method.
>
> The reason this is probably a better approach for most tests is that
> most people don't really care about testing the Shiro SecurityManager
> and Subject implementations - they typically want to test their own
> code that relies on SecurityUtils.getSubject() and the Subject API.
> Creating and using the actual SecurityManager and Subject
> implementation instances (as is shown in the current testing.html
> documentation) is probably better suited for integration tests.
>
> I'll update the documentation to reflect this approach.
>
> HTH!
>
> Best,
>
> Les
>
> On Tue, Dec 7, 2010 at 7:45 AM, Tauren Mills <[email protected]> wrote:
>> I'm following the instructions on how to do unit testing with Shiro:
>> http://shiro.apache.org/testing.html
>> I've got everything compiling and running. However, I'm unclear on how to
>> actually specify the subject I want to use. The following creates a
>> DelegatingSubject, but it appears to be unauthenticated with no principles
>> or anything. I know I haven't properly set them, but I'm unsure the right
>> way to do it.
>>         Subject subjectUnderTest = new
>> Subject.Builder(getSecurityManager()).buildSubject();
>> My application uses Spring to configure Shiro and it has a custom realm that
>> creates permissions. Do I need to create another realm to use only during
>> testing? Or can I use my curent realm and force a specific user
>> authentication?  For instance, I'd like to run my tests assuming that the
>> user with an ID of 1 has authenticated.
>> Following the testing instructions, I've set up an INI file that gets
>> loaded, even though with my normal application, I use Spring to configure
>> Shiro. It seems like going with an INI for testing might be simpler. Should
>> I be using Spring to configure Shiro for unit testing, or is using INI just
>> fine?
>> [main]
>> sha256Matcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher
>> rememberMeManager = com.company.security.MyRememberMeManager
>> rememberMeManager.cipherKey = xymVvsqSTov2/tcoHnax0B==
>> myRealm = com.company.security.MyRealm
>> myRealm.credentialsMatcher = $sha256Matcher
>> securityManager.sessionManager.globalSessionTimeout = 1800000
>> securityManager.rememberMeManager = $rememberMeManager
>> [users]
>> [roles]
>> So what is the simplest way to make user ID 1 authenticated? Should I create
>> a custom Realm for testing that has the user hard coded into
>> doGetAuthenticationInfo? Or should I be specify the user in the [users]
>> section and somehow use it? Or can I pass a custom AuthenticationToken with
>> the proper details to my current Realm implementation? How would I do that?
>>     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken
>> authcToken) throws AuthenticationException {
>>         UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
>>         Member member = memberService.findMember(token.getUsername());
>>         if (member != null && member.isValidated()) {
>>             return new SimpleAuthenticationInfo(member.getId(),
>> member.getPassword(), getName());
>>         } else {
>>             return null;
>>         }
>>     }
>> Ideally, I'd just build an AuthenticationToken and somehow pass it to the
>> realm.doGetAuthInfo() method. But I'm unclear how that would be
>> accomplished.
>> Thanks!
>> Tauren

Reply via email to